1use binaryninjacore_sys::*;
18use std::fmt::{Debug, Formatter};
19use std::ptr::NonNull;
20
21use crate::architecture::CoreArchitecture;
22use crate::binary_view::BinaryView;
23
24use crate::function::Function;
25use crate::rc::*;
26use crate::string::*;
27
28pub type TagTypeType = BNTagTypeType;
29pub type TagReferenceType = BNTagReferenceType;
30
31pub struct Tag {
32 pub(crate) handle: *mut BNTag,
33}
34
35impl Tag {
36 pub(crate) unsafe fn from_raw(handle: *mut BNTag) -> Self {
37 debug_assert!(!handle.is_null());
38 Self { handle }
39 }
40
41 pub(crate) unsafe fn ref_from_raw(handle: *mut BNTag) -> Ref<Self> {
42 debug_assert!(!handle.is_null());
43 Ref::new(Self { handle })
44 }
45
46 pub fn new(t: &TagType, data: &str) -> Ref<Self> {
47 let data = data.to_cstr();
48 unsafe { Self::ref_from_raw(BNCreateTag(t.handle, data.as_ptr())) }
49 }
50
51 pub fn id(&self) -> String {
52 unsafe { BnString::into_string(BNTagGetId(self.handle)) }
53 }
54
55 pub fn data(&self) -> String {
56 unsafe { BnString::into_string(BNTagGetData(self.handle)) }
57 }
58
59 pub fn ty(&self) -> Ref<TagType> {
60 unsafe { TagType::ref_from_raw(BNTagGetType(self.handle)) }
61 }
62
63 pub fn set_data(&self, data: &str) {
64 let data = data.to_cstr();
65 unsafe {
66 BNTagSetData(self.handle, data.as_ptr());
67 }
68 }
69}
70
71impl Debug for Tag {
72 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
73 f.debug_struct("Tag")
74 .field("id", &self.id())
75 .field("data", &self.data())
76 .field("type", &self.ty())
77 .finish()
78 }
79}
80
81impl PartialEq for Tag {
82 fn eq(&self, other: &Self) -> bool {
83 self.id() == other.id()
84 }
85}
86
87impl Eq for Tag {}
88
89unsafe impl RefCountable for Tag {
90 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
91 Ref::new(Self {
92 handle: BNNewTagReference(handle.handle),
93 })
94 }
95
96 unsafe fn dec_ref(handle: &Self) {
97 BNFreeTag(handle.handle);
98 }
99}
100
101impl ToOwned for Tag {
102 type Owned = Ref<Self>;
103
104 fn to_owned(&self) -> Self::Owned {
105 unsafe { RefCountable::inc_ref(self) }
106 }
107}
108
109impl CoreArrayProvider for Tag {
110 type Raw = *mut BNTag;
111 type Context = ();
112 type Wrapped<'a> = Guard<'a, Tag>;
113}
114
115unsafe impl CoreArrayProviderInner for Tag {
116 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
117 BNFreeTagList(raw, count)
118 }
119
120 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
121 Guard::new(Self { handle: *raw }, &context)
122 }
123}
124
125unsafe impl Send for Tag {}
126unsafe impl Sync for Tag {}
127
128pub struct TagType {
129 pub(crate) handle: *mut BNTagType,
130}
131
132impl CoreArrayProvider for TagType {
133 type Raw = *mut BNTagType;
134 type Context = ();
135 type Wrapped<'a> = Guard<'a, Self>;
136}
137
138unsafe impl CoreArrayProviderInner for TagType {
139 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
140 BNFreeTagTypeList(raw, count)
141 }
142
143 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
144 Guard::new(Self::from_raw(*raw), context)
145 }
146}
147
148impl TagType {
149 pub(crate) unsafe fn from_raw(handle: *mut BNTagType) -> Self {
150 debug_assert!(!handle.is_null());
151 Self { handle }
152 }
153
154 pub(crate) unsafe fn ref_from_raw(handle: *mut BNTagType) -> Ref<Self> {
155 debug_assert!(!handle.is_null());
156 Ref::new(Self { handle })
157 }
158
159 pub fn create(view: &BinaryView, name: &str, icon: &str) -> Ref<Self> {
160 let tag_type = unsafe { Self::ref_from_raw(BNCreateTagType(view.handle)) };
161 tag_type.set_name(name);
162 tag_type.set_icon(icon);
163 tag_type.set_type(TagTypeType::UserTagType);
164 tag_type
165 }
166
167 pub fn id(&self) -> String {
168 unsafe { BnString::into_string(BNTagTypeGetId(self.handle)) }
169 }
170
171 pub fn icon(&self) -> String {
172 unsafe { BnString::into_string(BNTagTypeGetIcon(self.handle)) }
173 }
174
175 pub fn set_icon(&self, icon: &str) {
176 let icon = icon.to_cstr();
177 unsafe {
178 BNTagTypeSetIcon(self.handle, icon.as_ptr());
179 }
180 }
181
182 pub fn name(&self) -> String {
183 unsafe { BnString::into_string(BNTagTypeGetName(self.handle)) }
184 }
185
186 pub fn set_name(&self, name: &str) {
187 let name = name.to_cstr();
188 unsafe {
189 BNTagTypeSetName(self.handle, name.as_ptr());
190 }
191 }
192
193 pub fn visible(&self) -> bool {
194 unsafe { BNTagTypeGetVisible(self.handle) }
195 }
196
197 pub fn set_visible(&self, visible: bool) {
198 unsafe { BNTagTypeSetVisible(self.handle, visible) }
199 }
200
201 pub fn ty(&self) -> TagTypeType {
202 unsafe { BNTagTypeGetType(self.handle) }
203 }
204
205 pub fn set_type(&self, ty: TagTypeType) {
206 unsafe {
207 BNTagTypeSetType(self.handle, ty);
208 }
209 }
210
211 pub fn view(&self) -> Ref<BinaryView> {
212 unsafe { BinaryView::ref_from_raw(BNTagTypeGetView(self.handle)) }
213 }
214}
215
216impl Debug for TagType {
217 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
218 f.debug_struct("TagType")
219 .field("id", &self.id())
220 .field("name", &self.name())
221 .field("icon", &self.icon())
222 .field("visible", &self.visible())
223 .field("type", &self.ty())
224 .finish()
225 }
226}
227
228impl PartialEq for TagType {
229 fn eq(&self, other: &Self) -> bool {
230 self.id() == other.id()
231 }
232}
233
234impl Eq for TagType {}
235
236unsafe impl RefCountable for TagType {
237 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
238 Ref::new(Self {
239 handle: BNNewTagTypeReference(handle.handle),
240 })
241 }
242
243 unsafe fn dec_ref(handle: &Self) {
244 BNFreeTagType(handle.handle);
245 }
246}
247
248impl ToOwned for TagType {
249 type Owned = Ref<Self>;
250
251 fn to_owned(&self) -> Self::Owned {
252 unsafe { RefCountable::inc_ref(self) }
253 }
254}
255
256unsafe impl Send for TagType {}
257unsafe impl Sync for TagType {}
258
259#[derive(Clone, PartialEq)]
260pub struct TagReference {
261 pub arch: Option<CoreArchitecture>,
262 pub func: Option<Ref<Function>>,
263 pub addr: u64,
264 pub auto_defined: bool,
265 pub reference_type: TagReferenceType,
266 pub tag: Ref<Tag>,
267}
268
269impl From<&BNTagReference> for TagReference {
270 fn from(value: &BNTagReference) -> Self {
271 Self {
272 reference_type: value.refType,
273 auto_defined: value.autoDefined,
274 tag: unsafe { Tag::from_raw(value.tag).to_owned() },
275 arch: NonNull::new(value.arch)
276 .map(|arch| unsafe { CoreArchitecture::from_raw(arch.as_ptr()) }),
277 func: NonNull::new(value.func)
278 .map(|func| unsafe { Function::from_raw(func.as_ptr()).to_owned() }),
279 addr: value.addr,
280 }
281 }
282}
283
284impl Debug for TagReference {
285 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
286 f.debug_struct("TagReference")
287 .field("addr", &self.addr)
288 .field("auto_defined", &self.auto_defined)
289 .field("reference_type", &self.reference_type)
290 .field("tag", &self.tag)
291 .finish()
292 }
293}
294
295impl CoreArrayProvider for TagReference {
296 type Raw = BNTagReference;
297 type Context = ();
298 type Wrapped<'a> = Self;
299}
300
301unsafe impl CoreArrayProviderInner for TagReference {
302 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
303 BNFreeTagReferences(raw, count)
304 }
305
306 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
307 raw.into()
308 }
309}