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