1use std::ffi::c_void;
2
3use imgui::{ImColor32, ImStr, Ui};
4
5
6type ReadHandler<'a, T> = Option<Box<dyn FnMut(&T, usize) -> u8 + 'a>>;
8type WriteHandler<'a, T> = Option<Box<dyn FnMut(&mut T, usize, u8) + 'a>>;
9type HighlightHandler<'a, T> = Option<Box<dyn FnMut(&T, usize) -> bool + 'a>>;
10type MemData<'a, 'b, T> = (
11 &'b mut ReadHandler<'a, T>,
12 &'b mut WriteHandler<'a, T>,
13 &'b mut HighlightHandler<'a, T>,
14 &'b mut T
15);
16
17pub struct MemoryEditor<'a, T> {
18 window_name: Option<&'a ImStr>,
19 read_fn: ReadHandler<'a, T>,
20 write_fn: WriteHandler<'a, T>,
21 highlight_fn: HighlightHandler<'a, T>,
22 mem_size: usize,
23 base_addr: usize,
24 raw: sys::MemoryEditor,
25}
26
27impl<'a, T> MemoryEditor<'a, T> {
28 pub fn new() -> MemoryEditor<'a, T> {
29 let mut raw = Default::default();
30 unsafe { sys::Editor_Create(&mut raw) }
31 MemoryEditor {
32 window_name: None,
33 read_fn: None,
34 write_fn: None,
35 highlight_fn: None,
36 mem_size: 0,
37 base_addr: 0,
38 raw,
39 }
40 }
41
42 #[inline]
44 pub fn mem_size(mut self, mem_size: usize) -> Self {
45 self.mem_size = mem_size;
46 self
47 }
48
49 #[inline]
51 pub fn base_addr(mut self, base_addr: usize) -> Self {
52 self.base_addr = base_addr;
53 self
54 }
55
56 #[inline]
58 pub fn open(&self) -> bool {
59 self.raw.Open
60 }
61 #[inline]
63 pub fn read_only(mut self, read_only: bool) -> Self {
64 self.raw.ReadOnly = read_only;
65 self
66 }
67 #[inline]
69 pub fn cols(mut self, cols: i32) -> Self {
70 self.raw.Cols = cols;
71 self
72 }
73 #[inline]
75 pub fn show_options(mut self, show_options: bool) -> Self {
76 self.raw.OptShowOptions = show_options;
77 self
78 }
79 #[inline]
81 pub fn show_data_preview(mut self, show_data_preview: bool) -> Self {
82 self.raw.OptShowDataPreview = show_data_preview;
83 self
84 }
85 #[inline]
87 pub fn show_hexii(mut self, show_hexii: bool) -> Self {
88 self.raw.OptShowHexII = show_hexii;
89 self
90 }
91 #[inline]
93 pub fn show_ascii(mut self, show_ascii: bool) -> Self {
94 self.raw.OptShowAscii = show_ascii;
95 self
96 }
97 #[inline]
99 pub fn grey_out_zeroes(mut self, grey_out_zeroes: bool) -> Self {
100 self.raw.OptGreyOutZeroes = grey_out_zeroes;
101 self
102 }
103 #[inline]
105 pub fn upper_case_hex(mut self, upper_case_hex: bool) -> Self {
106 self.raw.OptUpperCaseHex = upper_case_hex;
107 self
108 }
109 #[inline]
111 pub fn mid_cols_count(mut self, mid_cols_count: i32) -> Self {
112 self.raw.OptMidColsCount = mid_cols_count;
113 self
114 }
115 #[inline]
117 pub fn addr_digits_count(mut self, addr_digits_count: i32) -> Self {
118 self.raw.OptAddrDigitsCount = addr_digits_count;
119 self
120 }
121 #[inline]
123 pub fn highlight_color(mut self, color: ImColor32) -> Self {
124 self.raw.HighlightColor = color.into();
125 self
126 }
127 #[inline]
129 pub fn read_fn<F>(mut self, read_fn: F) -> Self where F: FnMut(&T, usize) -> u8 + 'a {
130 self.read_fn = Some(Box::new(read_fn));
131 self
132 }
133 #[inline]
135 pub fn write_fn<F>(mut self, write_fn: F) -> Self where F: FnMut(&mut T, usize, u8) + 'a {
136 self.write_fn = Some(Box::new(write_fn));
137 self
138 }
139 #[inline]
141 pub fn highlight_fn<F>(mut self, highlight_fn: F) -> Self where F: FnMut(&T, usize) -> bool + 'a {
142 self.highlight_fn = Some(Box::new(highlight_fn));
143 self
144 }
145
146 #[inline]
148 pub fn draw_window(mut self, window_name: &'a ImStr) -> Self {
149 self.window_name = Some(window_name);
150 self
151 }
152 #[inline]
154 pub fn no_window(mut self) -> Self {
155 self.window_name = None;
156 self
157 }
158
159 pub fn draw(&mut self, _: &Ui, user_data: &mut T) {
161 assert!(
162 self.read_fn.is_some() || self.mem_size == 0,
163 "Read Fn must be set if mem size > 0"
164 );
165 assert!(
166 self.write_fn.is_some() || self.raw.ReadOnly || self.mem_size == 0,
167 "Write Fn must be set if not read only and mem size > 0"
168 );
169 self.raw.ReadFn = Some(read_wrapper::<T>);
170 self.raw.WriteFn = Some(write_wrapper::<T>);
171 self.raw.HighlightFn = if self.highlight_fn.is_some() { Some(highlight_wrapper::<T>) } else { None };
172
173 let mut data = (
174 &mut self.read_fn,
175 &mut self.write_fn,
176 &mut self.highlight_fn,
177 user_data
178 );
179 let mem_data = &mut data as *mut MemData<T> as *mut c_void;
180 unsafe { self.draw_raw(mem_data) }
181 }
182
183 pub unsafe fn draw_raw(&mut self, mem_data: *mut c_void) {
184 if let Some(title) = self.window_name {
185 sys::Editor_DrawWindow(
186 &mut self.raw,
187 title.as_ptr(),
188 mem_data,
189 self.mem_size,
190 self.base_addr,
191 );
192 } else {
193 sys::Editor_DrawContents(
194 &mut self.raw,
195 mem_data,
196 self.mem_size,
197 self.base_addr,
198 );
199 }
200 }
201}
202
203impl<'a> MemoryEditor<'a, &[u8]> {
204 pub fn draw_vec(&mut self, _: &Ui, data: &[u8]) {
205 assert!(!self.raw.ReadOnly, "Data muse be a mutable slice if editor is not read only");
206 assert!(
208 self.read_fn.is_none() && self.write_fn.is_none() && self.highlight_fn.is_none(),
209 "Handler functions not supported when using draw_vec. Use draw instead"
210 );
211 self.mem_size = data.len();
212 unsafe { self.draw_raw(data.as_ptr() as *mut c_void) }
213 }
214}
215
216
217impl<'a> MemoryEditor<'a, &mut [u8]> {
219 pub fn draw_vec(&mut self, _: &Ui, data: &mut [u8]) {
220 assert!(
222 self.read_fn.is_none() && self.write_fn.is_none() && self.highlight_fn.is_none(),
223 "Handler functions not supported when using draw_vec. Use draw instead"
224 );
225 self.mem_size = data.len();
226 unsafe { self.draw_raw(data.as_mut_ptr() as *mut c_void) }
227 }
228}
229
230unsafe extern "C" fn read_wrapper<'a, T>(data: *const u8, off: usize) -> u8 {
232 let (read_fn, _, _, user_data) = &mut *(data as *mut MemData<T>);
233 read_fn.as_mut().unwrap()(user_data, off)
234}
235
236unsafe extern "C" fn write_wrapper<'a, T>(data: *mut u8, off: usize, d: u8) {
237 let (_, write_fn, _, user_data) = &mut *(data as *mut MemData<T>);
238 write_fn.as_mut().unwrap()(user_data, off, d);
239}
240
241unsafe extern "C" fn highlight_wrapper<'a, T>(data: *const u8, off: usize) -> bool {
242 let (_, _, highlight_fn, user_data) = &mut *(data as *mut MemData<T>);
243 highlight_fn.as_mut().unwrap()(user_data, off)
244}