binaryninja/
data_buffer.rs1use binaryninjacore_sys::*;
18
19use std::ffi::c_void;
20use std::slice;
21
22use crate::string::{BnString, IntoCStr};
23
24pub struct DataBuffer(*mut BNDataBuffer);
25
26impl DataBuffer {
27 pub(crate) fn from_raw(raw: *mut BNDataBuffer) -> Self {
28 DataBuffer(raw)
29 }
30
31 pub(crate) fn as_raw(&self) -> *mut BNDataBuffer {
32 self.0
33 }
34
35 pub fn new(data: &[u8]) -> Self {
36 let buffer = unsafe { BNCreateDataBuffer(data.as_ptr() as *const c_void, data.len()) };
37 assert!(!buffer.is_null());
38 DataBuffer::from_raw(buffer)
39 }
40
41 pub fn get_data(&self) -> &[u8] {
42 let buffer = unsafe { BNGetDataBufferContents(self.0) };
43 if buffer.is_null() {
44 &[]
45 } else {
46 unsafe { slice::from_raw_parts(buffer as *const _, self.len()) }
47 }
48 }
49
50 pub fn get_data_at(&self, offset: usize) -> &[u8] {
51 let len = self.len();
52 if offset > len {
53 panic!();
54 }
55 let slice_len = len - offset;
56 let buffer = unsafe { BNGetDataBufferContentsAt(self.0, offset) };
57 if buffer.is_null() {
58 &[]
59 } else {
60 unsafe { slice::from_raw_parts(buffer as *const _, slice_len) }
61 }
62 }
63
64 pub fn get_slice(&self, start: usize, len: usize) -> Option<Self> {
66 if start + len > self.len() {
67 return None;
68 }
69 let ptr = unsafe { BNGetDataBufferSlice(self.0, start, len) };
70 (!ptr.is_null()).then(|| Self(ptr))
71 }
72
73 pub unsafe fn set_len(&mut self, len: usize) {
76 unsafe { BNSetDataBufferLength(self.0, len) }
77 }
78
79 pub fn clear(&self) {
81 unsafe { BNClearDataBuffer(self.0) }
82 }
83
84 pub fn assign(dst: &mut Self, src: &Self) {
86 unsafe { BNAssignDataBuffer(dst.0, src.0) }
87 }
88
89 pub fn append(dst: &mut Self, src: &Self) {
91 unsafe { BNAppendDataBuffer(dst.0, src.0) }
92 }
93
94 pub fn append_data(&self, data: &[u8]) {
96 unsafe { BNAppendDataBufferContents(self.0, data.as_ptr() as *const c_void, data.len()) }
97 }
98
99 pub unsafe fn byte_at(&self, offset: usize) -> u8 {
101 unsafe { BNGetDataBufferByte(self.0, offset) }
102 }
103
104 pub unsafe fn set_byte_at(&mut self, offset: usize, byte: u8) {
106 unsafe { BNSetDataBufferByte(self.0, offset, byte) }
107 }
108
109 pub fn set_data(&mut self, data: &[u8]) {
110 unsafe {
111 BNSetDataBufferContents(
112 self.0,
113 data.as_ptr() as *const c_void as *mut c_void,
114 data.len(),
115 );
116 }
117 }
118
119 pub fn to_escaped_string(&self, null_terminates: bool, escape_printable: bool) -> String {
120 unsafe {
121 BnString::into_string(BNDataBufferToEscapedString(
122 self.0,
123 null_terminates,
124 escape_printable,
125 ))
126 }
127 }
128
129 pub fn from_escaped_string(value: &str) -> Self {
130 let value = value.to_cstr();
131 Self(unsafe { BNDecodeEscapedString(value.as_ptr()) })
132 }
133
134 pub fn to_base64(&self) -> String {
135 unsafe { BnString::into_string(BNDataBufferToBase64(self.0)) }
136 }
137
138 pub fn from_base64(value: &str) -> Self {
139 let t = value.to_cstr();
140 Self(unsafe { BNDecodeBase64(t.as_ptr()) })
141 }
142
143 pub fn zlib_compress(&self) -> Self {
144 Self(unsafe { BNZlibCompress(self.0) })
145 }
146
147 pub fn zlib_decompress(&self) -> Self {
148 Self(unsafe { BNZlibDecompress(self.0) })
149 }
150
151 pub fn lzma_decompress(&self) -> Self {
152 Self(unsafe { BNLzmaDecompress(self.0) })
153 }
154
155 pub fn lzma2_decompress(&self) -> Self {
156 Self(unsafe { BNLzma2Decompress(self.0) })
157 }
158
159 pub fn xz_decompress(&self) -> Self {
160 Self(unsafe { BNXzDecompress(self.0) })
161 }
162
163 pub fn len(&self) -> usize {
164 unsafe { BNGetDataBufferLength(self.0) }
165 }
166
167 pub fn is_empty(&self) -> bool {
168 self.len() == 0
169 }
170}
171
172impl Default for DataBuffer {
173 fn default() -> Self {
174 Self(unsafe { BNCreateDataBuffer([].as_ptr(), 0) })
175 }
176}
177
178impl Drop for DataBuffer {
179 fn drop(&mut self) {
180 unsafe {
181 BNFreeDataBuffer(self.0);
182 }
183 }
184}
185
186impl Clone for DataBuffer {
187 fn clone(&self) -> Self {
188 Self::from_raw(unsafe { BNDuplicateDataBuffer(self.0) })
189 }
190}
191
192impl From<&[u8]> for DataBuffer {
193 fn from(value: &[u8]) -> Self {
194 DataBuffer::new(value)
195 }
196}
197
198impl AsRef<[u8]> for DataBuffer {
199 fn as_ref(&self) -> &[u8] {
200 self.get_data()
201 }
202}
203
204impl std::borrow::Borrow<[u8]> for DataBuffer {
205 fn borrow(&self) -> &[u8] {
206 self.as_ref()
207 }
208}
209
210macro_rules! data_buffer_index {
211 ($range:ty, $output:ty) => {
212 impl std::ops::Index<$range> for DataBuffer {
213 type Output = $output;
214
215 fn index(&self, index: $range) -> &Self::Output {
216 &self.get_data()[index]
217 }
218 }
219 };
220}
221
222data_buffer_index!(usize, u8);
223data_buffer_index!(std::ops::Range<usize>, [u8]);
224data_buffer_index!(std::ops::RangeInclusive<usize>, [u8]);
225data_buffer_index!(std::ops::RangeTo<usize>, [u8]);
226data_buffer_index!(std::ops::RangeFull, [u8]);
227
228impl PartialEq for DataBuffer {
229 fn eq(&self, other: &Self) -> bool {
230 self.as_ref() == other.as_ref()
231 }
232}
233impl Eq for DataBuffer {}
234
235impl PartialOrd for DataBuffer {
236 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
237 Some(self.as_ref().cmp(other.as_ref()))
238 }
239}
240
241impl Ord for DataBuffer {
242 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
243 self.as_ref().cmp(other.as_ref())
244 }
245}