1use std::{
2 collections::{HashMap, HashSet},
3 fmt::Debug,
4 hash::Hash,
5};
6
7use vmi_core::{AddressContext, View};
8
9pub trait KeyType: Debug + Copy + Eq + Hash {}
11impl<T> KeyType for T where T: Debug + Copy + Eq + Hash {}
12
13pub trait TagType: Debug + Copy + Eq + Hash {}
18impl<T> TagType for T where T: Debug + Copy + Eq + Hash {}
19
20pub(super) type ActiveBreakpoints<Key, Tag> =
21 HashMap<(Key, AddressContext), HashSet<Breakpoint<Key, Tag>>>;
22pub(super) type PendingBreakpoints<Key, Tag> = HashSet<Breakpoint<Key, Tag>>;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
33pub struct Breakpoint<Key, Tag>
34where
35 Key: KeyType,
36 Tag: TagType,
37{
38 pub(super) ctx: AddressContext,
39 pub(super) view: View,
40 pub(super) global: bool,
41 pub(super) key: Key,
42 pub(super) tag: Tag,
43}
44
45impl<Key, Tag> Breakpoint<Key, Tag>
46where
47 Key: KeyType,
48 Tag: TagType,
49{
50 pub fn ctx(&self) -> AddressContext {
55 self.ctx
56 }
57
58 pub fn view(&self) -> View {
60 self.view
61 }
62
63 pub fn global(&self) -> bool {
69 self.global
70 }
71
72 pub fn key(&self) -> Key {
74 self.key
75 }
76
77 pub fn tag(&self) -> Tag {
79 self.tag
80 }
81}
82
83#[derive(Debug)]
89pub struct BreakpointBuilder {
90 ctx: AddressContext,
91 view: View,
92 global: bool,
93}
94
95#[doc(hidden)]
96#[derive(Debug)]
97pub struct BreakpointBuilderWithKey<Key>
98where
99 Key: KeyType,
100{
101 ctx: AddressContext,
102 view: View,
103 global: bool,
104 key: Key,
105}
106
107#[doc(hidden)]
108#[derive(Debug)]
109pub struct BreakpointBuilderWithTag<Tag>
110where
111 Tag: TagType,
112{
113 ctx: AddressContext,
114 view: View,
115 global: bool,
116 tag: Tag,
117}
118
119#[doc(hidden)]
120#[derive(Debug)]
121pub struct BreakpointBuilderWithKeyTag<Key, Tag>
122where
123 Key: KeyType,
124 Tag: TagType,
125{
126 ctx: AddressContext,
127 view: View,
128 global: bool,
129 key: Key,
130 tag: Tag,
131}
132
133impl Breakpoint<(), ()> {
134 #[expect(clippy::new_ret_no_self)]
136 pub fn new(ctx: impl Into<AddressContext>, view: View) -> BreakpointBuilder {
137 BreakpointBuilder::new(ctx, view)
138 }
139}
140
141impl BreakpointBuilder {
142 pub fn new(ctx: impl Into<AddressContext>, view: View) -> Self {
144 Self {
145 ctx: ctx.into(),
146 view,
147 global: false,
148 }
149 }
150
151 pub fn global(self) -> Self {
157 Self {
158 global: true,
159 ..self
160 }
161 }
162
163 pub fn with_key<Key>(self, key: Key) -> BreakpointBuilderWithKey<Key>
165 where
166 Key: KeyType,
167 {
168 BreakpointBuilderWithKey {
169 ctx: self.ctx,
170 view: self.view,
171 global: self.global,
172 key,
173 }
174 }
175
176 pub fn with_tag<Tag>(self, tag: Tag) -> BreakpointBuilderWithTag<Tag>
178 where
179 Tag: TagType,
180 {
181 BreakpointBuilderWithTag {
182 ctx: self.ctx,
183 view: self.view,
184 global: self.global,
185 tag,
186 }
187 }
188}
189
190impl<Key> BreakpointBuilderWithKey<Key>
191where
192 Key: KeyType,
193{
194 pub fn with_tag<Tag>(self, tag: Tag) -> BreakpointBuilderWithKeyTag<Key, Tag>
196 where
197 Tag: TagType,
198 {
199 BreakpointBuilderWithKeyTag {
200 ctx: self.ctx,
201 view: self.view,
202 global: self.global,
203 key: self.key,
204 tag,
205 }
206 }
207}
208
209impl<Tag> BreakpointBuilderWithTag<Tag>
210where
211 Tag: TagType,
212{
213 pub fn with_key<Key>(self, key: Key) -> BreakpointBuilderWithKeyTag<Key, Tag>
215 where
216 Key: KeyType,
217 {
218 BreakpointBuilderWithKeyTag {
219 ctx: self.ctx,
220 view: self.view,
221 global: self.global,
222 key,
223 tag: self.tag,
224 }
225 }
226}
227
228impl<Key, Tag> From<BreakpointBuilder> for Breakpoint<Key, Tag>
229where
230 Key: KeyType + Default,
231 Tag: TagType + Default,
232{
233 fn from(value: BreakpointBuilder) -> Self {
234 Self {
235 ctx: value.ctx,
236 view: value.view,
237 global: value.global,
238 key: Default::default(),
239 tag: Default::default(),
240 }
241 }
242}
243
244impl<Key, Tag> From<BreakpointBuilderWithKey<Key>> for Breakpoint<Key, Tag>
245where
246 Key: KeyType,
247 Tag: TagType + Default,
248{
249 fn from(value: BreakpointBuilderWithKey<Key>) -> Self {
250 Self {
251 ctx: value.ctx,
252 view: value.view,
253 global: value.global,
254 key: value.key,
255 tag: Default::default(),
256 }
257 }
258}
259
260impl<Key, Tag> From<BreakpointBuilderWithTag<Tag>> for Breakpoint<Key, Tag>
261where
262 Key: KeyType + Default,
263 Tag: TagType,
264{
265 fn from(value: BreakpointBuilderWithTag<Tag>) -> Self {
266 Self {
267 ctx: value.ctx,
268 view: value.view,
269 global: value.global,
270 key: Default::default(),
271 tag: value.tag,
272 }
273 }
274}
275
276impl<Key, Tag> From<BreakpointBuilderWithKeyTag<Key, Tag>> for Breakpoint<Key, Tag>
277where
278 Key: KeyType,
279 Tag: TagType,
280{
281 fn from(value: BreakpointBuilderWithKeyTag<Key, Tag>) -> Self {
282 Self {
283 ctx: value.ctx,
284 view: value.view,
285 global: value.global,
286 key: value.key,
287 tag: value.tag,
288 }
289 }
290}