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