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