1use std::marker::PhantomData;
2
3use crate::ffi::hexrays::{
4 cblock_iter, cblock_t, cfunc_t, cfuncptr_t, cinsn_t, idalib_hexrays_cblock_iter,
5 idalib_hexrays_cblock_iter_next, idalib_hexrays_cblock_len, idalib_hexrays_cfunc_body,
6 idalib_hexrays_cfunc_pseudocode, idalib_hexrays_cfuncptr_inner,
7};
8use crate::idb::IDB;
9
10pub use crate::ffi::hexrays::{HexRaysError, HexRaysErrorCode};
11
12pub struct CFunction<'a> {
13 ptr: *mut cfunc_t,
14 _obj: cxx::UniquePtr<cfuncptr_t>,
15 _marker: PhantomData<&'a IDB>,
16}
17
18pub struct CBlock<'a> {
19 ptr: *mut cblock_t,
20 _marker: PhantomData<&'a ()>,
21}
22
23pub struct CBlockIter<'a> {
24 it: cxx::UniquePtr<cblock_iter>,
25 _marker: PhantomData<&'a ()>,
26}
27
28impl<'a> Iterator for CBlockIter<'a> {
29 type Item = CInsn<'a>;
30
31 fn next(&mut self) -> Option<Self::Item> {
32 let ptr = unsafe { idalib_hexrays_cblock_iter_next(self.it.pin_mut()) };
33
34 if ptr.is_null() {
35 None
36 } else {
37 Some(CInsn {
38 ptr,
39 _marker: PhantomData,
40 })
41 }
42 }
43}
44
45pub struct CInsn<'a> {
46 #[allow(unused)]
47 ptr: *mut cinsn_t,
48 _marker: PhantomData<&'a ()>,
49}
50
51impl<'a> CFunction<'a> {
52 pub(crate) fn new(obj: cxx::UniquePtr<cfuncptr_t>) -> Option<Self> {
53 let ptr = unsafe { idalib_hexrays_cfuncptr_inner(obj.as_ref().expect("valid pointer")) };
54
55 if ptr.is_null() {
56 return None;
57 }
58
59 Some(Self {
60 ptr,
61 _obj: obj,
62 _marker: PhantomData,
63 })
64 }
65
66 pub fn pseudocode(&self) -> String {
67 unsafe { idalib_hexrays_cfunc_pseudocode(self.ptr) }
68 }
69
70 pub(crate) fn as_ptr(&self) -> *mut cfunc_t {
71 self.ptr
72 }
73
74 pub fn body(&self) -> CBlock<'_> {
75 let ptr = unsafe { idalib_hexrays_cfunc_body(self.ptr) };
76
77 CBlock {
78 ptr,
79 _marker: PhantomData,
80 }
81 }
82}
83
84impl<'a> CBlock<'a> {
85 pub fn iter(&self) -> CBlockIter<'_> {
86 CBlockIter {
87 it: unsafe { idalib_hexrays_cblock_iter(self.ptr) },
88 _marker: PhantomData,
89 }
90 }
91
92 pub fn len(&self) -> usize {
93 unsafe { idalib_hexrays_cblock_len(self.ptr) }
94 }
95
96 pub fn is_empty(&self) -> bool {
97 self.len() == 0
98 }
99}