1use binaryninjacore_sys::*;
18use std::ffi::c_char;
19use std::fmt::Debug;
20
21use crate::binary_view::BinaryView;
22use crate::rc::*;
23use crate::string::{BnString, IntoCStr};
24
25use crate::function::Function;
26
27pub type SettingsScope = BNSettingsScope;
28
29pub const DEFAULT_INSTANCE_ID: &str = "default";
30pub const GLOBAL_INSTANCE_ID: &str = "";
31
32#[derive(PartialEq, Eq, Hash)]
33pub struct Settings {
34 pub(crate) handle: *mut BNSettings,
35}
36
37impl Settings {
38 pub(crate) unsafe fn ref_from_raw(handle: *mut BNSettings) -> Ref<Self> {
39 debug_assert!(!handle.is_null());
40 Ref::new(Self { handle })
41 }
42
43 pub fn new() -> Ref<Self> {
44 Self::new_with_id(GLOBAL_INSTANCE_ID)
45 }
46
47 pub fn new_with_id(instance_id: &str) -> Ref<Self> {
48 let instance_id = instance_id.to_cstr();
49 unsafe { Self::ref_from_raw(BNCreateSettings(instance_id.as_ptr())) }
50 }
51
52 pub fn set_resource_id(&self, resource_id: &str) {
53 let resource_id = resource_id.to_cstr();
54 unsafe { BNSettingsSetResourceId(self.handle, resource_id.as_ptr()) };
55 }
56
57 pub fn serialize_schema(&self) -> String {
58 unsafe { BnString::into_string(BNSettingsSerializeSchema(self.handle)) }
59 }
60
61 pub fn deserialize_schema(&self, schema: &str) -> bool {
62 self.deserialize_schema_with_scope(schema, SettingsScope::SettingsAutoScope)
63 }
64
65 pub fn deserialize_schema_with_scope(&self, schema: &str, scope: SettingsScope) -> bool {
66 let schema = schema.to_cstr();
67 unsafe { BNSettingsDeserializeSchema(self.handle, schema.as_ptr(), scope, true) }
68 }
69
70 pub fn contains(&self, key: &str) -> bool {
71 let key = key.to_cstr();
72
73 unsafe { BNSettingsContains(self.handle, key.as_ptr()) }
74 }
75
76 pub fn keys(&self) -> Array<BnString> {
77 let mut count = 0;
78 let result = unsafe { BNSettingsKeysList(self.handle, &mut count) };
79 assert!(!result.is_null());
80 unsafe { Array::new(result as *mut *mut c_char, count, ()) }
81 }
82
83 pub fn get_bool(&self, key: &str) -> bool {
84 self.get_bool_with_opts(key, &mut QueryOptions::default())
85 }
86
87 pub fn get_bool_with_opts(&self, key: &str, options: &mut QueryOptions) -> bool {
88 let key = key.to_cstr();
89 let view_ptr = match options.view.as_ref() {
90 Some(view) => view.handle,
91 _ => std::ptr::null_mut(),
92 };
93 let func_ptr = match options.function.as_ref() {
94 Some(func) => func.handle,
95 _ => std::ptr::null_mut(),
96 };
97 unsafe {
98 BNSettingsGetBool(
99 self.handle,
100 key.as_ptr(),
101 view_ptr,
102 func_ptr,
103 &mut options.scope,
104 )
105 }
106 }
107
108 pub fn get_double(&self, key: &str) -> f64 {
109 self.get_double_with_opts(key, &mut QueryOptions::default())
110 }
111
112 pub fn get_double_with_opts(&self, key: &str, options: &mut QueryOptions) -> f64 {
113 let key = key.to_cstr();
114 let view_ptr = match options.view.as_ref() {
115 Some(view) => view.handle,
116 _ => std::ptr::null_mut(),
117 };
118 let func_ptr = match options.function.as_ref() {
119 Some(func) => func.handle,
120 _ => std::ptr::null_mut(),
121 };
122 unsafe {
123 BNSettingsGetDouble(
124 self.handle,
125 key.as_ptr(),
126 view_ptr,
127 func_ptr,
128 &mut options.scope,
129 )
130 }
131 }
132
133 pub fn get_integer(&self, key: &str) -> u64 {
134 self.get_integer_with_opts(key, &mut QueryOptions::default())
135 }
136
137 pub fn get_integer_with_opts(&self, key: &str, options: &mut QueryOptions) -> u64 {
138 let key = key.to_cstr();
139 let view_ptr = match options.view.as_ref() {
140 Some(view) => view.handle,
141 _ => std::ptr::null_mut(),
142 };
143 let func_ptr = match options.function.as_ref() {
144 Some(func) => func.handle,
145 _ => std::ptr::null_mut(),
146 };
147 unsafe {
148 BNSettingsGetUInt64(
149 self.handle,
150 key.as_ptr(),
151 view_ptr,
152 func_ptr,
153 &mut options.scope,
154 )
155 }
156 }
157
158 pub fn get_string(&self, key: &str) -> String {
159 self.get_string_with_opts(key, &mut QueryOptions::default())
160 }
161
162 pub fn get_string_with_opts(&self, key: &str, options: &mut QueryOptions) -> String {
163 let key = key.to_cstr();
164 let view_ptr = match options.view.as_ref() {
165 Some(view) => view.handle,
166 _ => std::ptr::null_mut(),
167 };
168 let func_ptr = match options.function.as_ref() {
169 Some(func) => func.handle,
170 _ => std::ptr::null_mut(),
171 };
172 unsafe {
173 BnString::into_string(BNSettingsGetString(
174 self.handle,
175 key.as_ptr(),
176 view_ptr,
177 func_ptr,
178 &mut options.scope,
179 ))
180 }
181 }
182
183 pub fn get_string_list(&self, key: &str) -> Array<BnString> {
184 self.get_string_list_with_opts(key, &mut QueryOptions::default())
185 }
186
187 pub fn get_string_list_with_opts(
188 &self,
189 key: &str,
190 options: &mut QueryOptions,
191 ) -> Array<BnString> {
192 let key = key.to_cstr();
193 let view_ptr = match options.view.as_ref() {
194 Some(view) => view.handle,
195 _ => std::ptr::null_mut(),
196 };
197 let func_ptr = match options.function.as_ref() {
198 Some(func) => func.handle,
199 _ => std::ptr::null_mut(),
200 };
201 let mut size: usize = 0;
202 unsafe {
203 Array::new(
204 BNSettingsGetStringList(
205 self.handle,
206 key.as_ptr(),
207 view_ptr,
208 func_ptr,
209 &mut options.scope,
210 &mut size,
211 ) as *mut *mut c_char,
212 size,
213 (),
214 )
215 }
216 }
217
218 pub fn get_json(&self, key: &str) -> String {
219 self.get_json_with_opts(key, &mut QueryOptions::default())
220 }
221
222 pub fn get_json_with_opts(&self, key: &str, options: &mut QueryOptions) -> String {
223 let key = key.to_cstr();
224 let view_ptr = match options.view.as_ref() {
225 Some(view) => view.handle,
226 _ => std::ptr::null_mut(),
227 };
228 let func_ptr = match options.function.as_ref() {
229 Some(func) => func.handle,
230 _ => std::ptr::null_mut(),
231 };
232 unsafe {
233 BnString::into_string(BNSettingsGetJson(
234 self.handle,
235 key.as_ptr(),
236 view_ptr,
237 func_ptr,
238 &mut options.scope,
239 ))
240 }
241 }
242
243 pub fn set_bool(&self, key: &str, value: bool) {
244 self.set_bool_with_opts(key, value, &QueryOptions::default())
245 }
246
247 pub fn set_bool_with_opts(&self, key: &str, value: bool, options: &QueryOptions) {
248 let key = key.to_cstr();
249 let view_ptr = match options.view.as_ref() {
250 Some(view) => view.handle,
251 _ => std::ptr::null_mut(),
252 };
253 let func_ptr = match options.function.as_ref() {
254 Some(func) => func.handle,
255 _ => std::ptr::null_mut(),
256 };
257 unsafe {
258 BNSettingsSetBool(
259 self.handle,
260 view_ptr,
261 func_ptr,
262 options.scope,
263 key.as_ptr(),
264 value,
265 );
266 }
267 }
268
269 pub fn set_double(&self, key: &str, value: f64) {
270 self.set_double_with_opts(key, value, &QueryOptions::default())
271 }
272 pub fn set_double_with_opts(&self, key: &str, value: f64, options: &QueryOptions) {
273 let key = key.to_cstr();
274 let view_ptr = match options.view.as_ref() {
275 Some(view) => view.handle,
276 _ => std::ptr::null_mut(),
277 };
278 let func_ptr = match options.function.as_ref() {
279 Some(func) => func.handle,
280 _ => std::ptr::null_mut(),
281 };
282 unsafe {
283 BNSettingsSetDouble(
284 self.handle,
285 view_ptr,
286 func_ptr,
287 options.scope,
288 key.as_ptr(),
289 value,
290 );
291 }
292 }
293
294 pub fn set_integer(&self, key: &str, value: u64) {
295 self.set_integer_with_opts(key, value, &QueryOptions::default())
296 }
297
298 pub fn set_integer_with_opts(&self, key: &str, value: u64, options: &QueryOptions) {
299 let key = key.to_cstr();
300 let view_ptr = match options.view.as_ref() {
301 Some(view) => view.handle,
302 _ => std::ptr::null_mut(),
303 };
304 let func_ptr = match options.function.as_ref() {
305 Some(func) => func.handle,
306 _ => std::ptr::null_mut(),
307 };
308 unsafe {
309 BNSettingsSetUInt64(
310 self.handle,
311 view_ptr,
312 func_ptr,
313 options.scope,
314 key.as_ptr(),
315 value,
316 );
317 }
318 }
319
320 pub fn set_string(&self, key: &str, value: &str) {
321 self.set_string_with_opts(key, value, &QueryOptions::default())
322 }
323
324 pub fn set_string_with_opts(&self, key: &str, value: &str, options: &QueryOptions) {
325 let key = key.to_cstr();
326 let value = value.to_cstr();
327 let view_ptr = match options.view.as_ref() {
328 Some(view) => view.handle,
329 _ => std::ptr::null_mut(),
330 };
331 let func_ptr = match options.function.as_ref() {
332 Some(func) => func.handle,
333 _ => std::ptr::null_mut(),
334 };
335 unsafe {
336 BNSettingsSetString(
337 self.handle,
338 view_ptr,
339 func_ptr,
340 options.scope,
341 key.as_ptr(),
342 value.as_ptr(),
343 );
344 }
345 }
346
347 pub fn set_string_list<I: IntoIterator<Item = String>>(&self, key: &str, value: I) -> bool {
348 self.set_string_list_with_opts(key, value, &QueryOptions::default())
349 }
350
351 pub fn set_string_list_with_opts<I: IntoIterator<Item = String>>(
352 &self,
353 key: &str,
354 value: I,
355 options: &QueryOptions,
356 ) -> bool {
357 let key = key.to_cstr();
358 let raw_list: Vec<_> = value.into_iter().map(|s| s.to_cstr()).collect();
359 let mut raw_list_ptr: Vec<_> = raw_list.iter().map(|s| s.as_ptr()).collect();
360
361 let view_ptr = match options.view.as_ref() {
362 Some(view) => view.handle,
363 _ => std::ptr::null_mut(),
364 };
365 let func_ptr = match options.function.as_ref() {
366 Some(func) => func.handle,
367 _ => std::ptr::null_mut(),
368 };
369 unsafe {
370 BNSettingsSetStringList(
371 self.handle,
372 view_ptr,
373 func_ptr,
374 options.scope,
375 key.as_ptr(),
376 raw_list_ptr.as_mut_ptr(),
377 raw_list_ptr.len(),
378 )
379 }
380 }
381
382 pub fn set_json(&self, key: &str, value: &str) -> bool {
383 self.set_json_with_opts(key, value, &QueryOptions::default())
384 }
385
386 pub fn set_json_with_opts(&self, key: &str, value: &str, options: &QueryOptions) -> bool {
387 let key = key.to_cstr();
388 let value = value.to_cstr();
389 let view_ptr = match options.view.as_ref() {
390 Some(view) => view.handle,
391 _ => std::ptr::null_mut(),
392 };
393 let func_ptr = match options.function.as_ref() {
394 Some(func) => func.handle,
395 _ => std::ptr::null_mut(),
396 };
397 unsafe {
398 BNSettingsSetJson(
399 self.handle,
400 view_ptr,
401 func_ptr,
402 options.scope,
403 key.as_ptr(),
404 value.as_ptr(),
405 )
406 }
407 }
408
409 pub fn get_property_string(&self, key: &str, property: &str) -> String {
410 let key = key.to_cstr();
411 let property = property.to_cstr();
412 unsafe {
413 BnString::into_string(BNSettingsQueryPropertyString(
414 self.handle,
415 key.as_ptr(),
416 property.as_ptr(),
417 ))
418 }
419 }
420
421 pub fn get_property_string_list(&self, key: &str, property: &str) -> Array<BnString> {
422 let key = key.to_cstr();
423 let property = property.to_cstr();
424 let mut size: usize = 0;
425 unsafe {
426 Array::new(
427 BNSettingsQueryPropertyStringList(
428 self.handle,
429 key.as_ptr(),
430 property.as_ptr(),
431 &mut size,
432 ) as *mut *mut c_char,
433 size,
434 (),
435 )
436 }
437 }
438
439 pub fn update_bool_property(&self, key: &str, property: &str, value: bool) {
440 let key = key.to_cstr();
441 let property = property.to_cstr();
442 unsafe {
443 BNSettingsUpdateBoolProperty(self.handle, key.as_ptr(), property.as_ptr(), value);
444 }
445 }
446
447 pub fn update_integer_property(&self, key: &str, property: &str, value: u64) {
448 let key = key.to_cstr();
449 let property = property.to_cstr();
450 unsafe {
451 BNSettingsUpdateUInt64Property(self.handle, key.as_ptr(), property.as_ptr(), value);
452 }
453 }
454
455 pub fn update_double_property(&self, key: &str, property: &str, value: f64) {
456 let key = key.to_cstr();
457 let property = property.to_cstr();
458 unsafe {
459 BNSettingsUpdateDoubleProperty(self.handle, key.as_ptr(), property.as_ptr(), value);
460 }
461 }
462
463 pub fn update_string_property(&self, key: &str, property: &str, value: &str) {
464 let key = key.to_cstr();
465 let property = property.to_cstr();
466 let value = value.to_cstr();
467 unsafe {
468 BNSettingsUpdateStringProperty(
469 self.handle,
470 key.as_ptr(),
471 property.as_ptr(),
472 value.as_ptr(),
473 );
474 }
475 }
476
477 pub fn update_string_list_property<I: IntoIterator<Item = String>>(
478 &self,
479 key: &str,
480 property: &str,
481 value: I,
482 ) {
483 let key = key.to_cstr();
484 let property = property.to_cstr();
485 let raw_list: Vec<_> = value.into_iter().map(|s| s.to_cstr()).collect();
486 let mut raw_list_ptr: Vec<_> = raw_list.iter().map(|s| s.as_ptr()).collect();
487
488 unsafe {
489 BNSettingsUpdateStringListProperty(
490 self.handle,
491 key.as_ptr(),
492 property.as_ptr(),
493 raw_list_ptr.as_mut_ptr(),
494 raw_list_ptr.len(),
495 );
496 }
497 }
498
499 pub fn register_group(&self, group: &str, title: &str) -> bool {
500 let group = group.to_cstr();
501 let title = title.to_cstr();
502
503 unsafe { BNSettingsRegisterGroup(self.handle, group.as_ptr(), title.as_ptr()) }
504 }
505
506 pub fn register_setting_json(&self, group: &str, properties: &str) -> bool {
507 let group = group.to_cstr();
508 let properties = properties.to_cstr();
509
510 unsafe { BNSettingsRegisterSetting(self.handle, group.as_ptr(), properties.as_ptr()) }
511 }
512
513 }
515
516impl Default for Ref<Settings> {
517 fn default() -> Self {
518 Settings::new_with_id(DEFAULT_INSTANCE_ID)
519 }
520}
521
522unsafe impl Send for Settings {}
523unsafe impl Sync for Settings {}
524
525impl ToOwned for Settings {
526 type Owned = Ref<Self>;
527
528 fn to_owned(&self) -> Self::Owned {
529 unsafe { RefCountable::inc_ref(self) }
530 }
531}
532
533unsafe impl RefCountable for Settings {
534 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
535 Ref::new(Self {
536 handle: BNNewSettingsReference(handle.handle),
537 })
538 }
539
540 unsafe fn dec_ref(handle: &Self) {
541 BNFreeSettings(handle.handle);
542 }
543}
544
545#[derive(Debug, Clone)]
546pub struct QueryOptions<'a> {
547 pub scope: SettingsScope,
548 pub view: Option<&'a BinaryView>,
549 pub function: Option<Ref<Function>>,
550}
551
552impl<'a> QueryOptions<'a> {
553 pub fn new() -> Self {
554 Self::default()
555 }
556
557 pub fn new_with_view(view: &'a BinaryView) -> Self {
558 Self {
559 view: Some(view),
560 ..Default::default()
561 }
562 }
563
564 pub fn new_with_func(func: Ref<Function>) -> Self {
565 Self {
566 function: Some(func),
567 ..Default::default()
568 }
569 }
570
571 pub fn with_view(mut self, view: &'a BinaryView) -> Self {
573 self.view = Some(view);
574 self
575 }
576
577 pub fn with_scope(mut self, scope: SettingsScope) -> Self {
578 self.scope = scope;
579 self
580 }
581
582 pub fn with_function(mut self, function: Ref<Function>) -> Self {
584 self.function = Some(function);
585 self
586 }
587}
588
589impl Default for QueryOptions<'_> {
590 fn default() -> Self {
591 Self {
592 view: None,
593 scope: SettingsScope::SettingsAutoScope,
594 function: None,
595 }
596 }
597}