1use std::marker::PhantomData;
2
3use crate::ffi::bytes::idalib_get_bytes;
4use crate::ffi::strings::{
5 build_strlist, clear_strlist, get_strlist_qty, idalib_get_strlist_item_addr,
6 idalib_get_strlist_item_length,
7};
8use crate::ffi::BADADDR;
9
10use crate::idb::IDB;
11use crate::Address;
12
13pub type StringIndex = usize;
14
15pub struct StringList<'a> {
16 _marker: PhantomData<&'a IDB>,
17}
18
19impl<'a> StringList<'a> {
20 pub(crate) fn new(_: &'a IDB) -> Self {
21 Self {
22 _marker: PhantomData,
23 }
24 }
25
26 pub fn rebuild(&self) {
27 unsafe { build_strlist() }
28 }
29
30 pub fn clear(&self) {
31 unsafe { clear_strlist() }
32 }
33
34 pub fn get_by_index(&self, index: StringIndex) -> Option<String> {
35 let addr = self.get_address_by_index(index)?;
36 let size = self.get_length_by_index(index);
37
38 let mut buf = Vec::with_capacity(size);
40 let Ok(new_len) = (unsafe { idalib_get_bytes(addr.into(), &mut buf) }) else {
41 return None;
42 };
43 unsafe {
44 buf.set_len(new_len);
45 }
46
47 Some(String::from_utf8_lossy(&buf).into_owned())
49 }
50
51 pub fn get_address_by_index(&self, index: StringIndex) -> Option<Address> {
52 let addr = unsafe { idalib_get_strlist_item_addr(index) };
53 if addr == BADADDR {
54 None
55 } else {
56 Some(addr.into())
57 }
58 }
59
60 fn get_length_by_index(&self, index: StringIndex) -> usize {
61 unsafe { idalib_get_strlist_item_length(index) }
62 }
63
64 pub fn len(&self) -> StringIndex {
65 unsafe { get_strlist_qty() }
66 }
67
68 pub fn is_empty(&self) -> bool {
69 self.len() == 0
70 }
71}