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_pseudocode,
6 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 fn as_cfunc(&self) -> &cfunc_t {
71 unsafe { self.ptr.as_ref().expect("valid pointer") }
72 }
73
74 pub fn body(&self) -> CBlock {
75 let cf = self.as_cfunc();
76 let ptr = unsafe { cf.body.__bindgen_anon_1.cblock };
77
78 CBlock {
79 ptr,
80 _marker: PhantomData,
81 }
82 }
83}
84
85impl<'a> CBlock<'a> {
86 pub fn iter(&self) -> CBlockIter {
87 CBlockIter {
88 it: unsafe { idalib_hexrays_cblock_iter(self.ptr) },
89 _marker: PhantomData,
90 }
91 }
92
93 pub fn len(&self) -> usize {
94 unsafe { idalib_hexrays_cblock_len(self.ptr) }
95 }
96
97 pub fn is_empty(&self) -> bool {
98 self.len() == 0
99 }
100}