1717use binaryninjacore_sys:: * ;
1818
1919use std:: ffi:: c_void;
20- use std:: ptr;
2120use std:: slice;
2221
22+ use crate :: string:: BnString ;
23+
2324pub struct DataBuffer ( * mut BNDataBuffer ) ;
2425
2526impl DataBuffer {
@@ -31,10 +32,6 @@ impl DataBuffer {
3132 }
3233
3334 pub fn get_data ( & self ) -> & [ u8 ] {
34- if self . 0 . is_null ( ) {
35- // TODO : Change the default value and remove this
36- return & [ ] ;
37- }
3835 let buffer = unsafe { BNGetDataBufferContents ( self . 0 ) } ;
3936 if buffer. is_null ( ) {
4037 & [ ]
@@ -43,6 +40,65 @@ impl DataBuffer {
4340 }
4441 }
4542
43+ pub fn get_data_at ( & self , offset : usize ) -> & [ u8 ] {
44+ let len = self . len ( ) ;
45+ if offset > len {
46+ panic ! ( ) ;
47+ }
48+ let slice_len = len - offset;
49+ let buffer = unsafe { BNGetDataBufferContentsAt ( self . 0 , offset) } ;
50+ if buffer. is_null ( ) {
51+ & [ ]
52+ } else {
53+ unsafe { slice:: from_raw_parts ( buffer as * const _ , slice_len) }
54+ }
55+ }
56+
57+ /// Create a copy of a especified part of the data
58+ pub fn get_slice ( & self , start : usize , len : usize ) -> Option < Self > {
59+ if start + len > self . len ( ) {
60+ return None ;
61+ }
62+ let ptr = unsafe { BNGetDataBufferSlice ( self . 0 , start, len) } ;
63+ ( !ptr. is_null ( ) ) . then ( || Self ( ptr) )
64+ }
65+
66+ /// change the size of the allocated data, if new size is bigger data is
67+ /// need to be initialized
68+ pub unsafe fn set_len ( & mut self , len : usize ) {
69+ unsafe { BNSetDataBufferLength ( self . 0 , len) }
70+ }
71+
72+ /// set the size to 0
73+ pub fn clear ( & self ) {
74+ unsafe { BNClearDataBuffer ( self . 0 ) }
75+ }
76+
77+ /// Copy the contents of `src` into `dst`
78+ pub fn assign ( dst : & mut Self , src : & Self ) {
79+ unsafe { BNAssignDataBuffer ( dst. 0 , src. 0 ) }
80+ }
81+
82+ /// Concat the contents of `src` into `dst`
83+ pub fn append ( dst : & mut Self , src : & Self ) {
84+ unsafe { BNAppendDataBuffer ( dst. 0 , src. 0 ) }
85+ }
86+
87+ /// concat the contents of `data` into self
88+ pub fn append_data ( & self , data : & [ u8 ] ) {
89+ unsafe { BNAppendDataBufferContents ( self . 0 , data. as_ptr ( ) as * const c_void , data. len ( ) ) }
90+ }
91+
92+ /// Return the byte at `offset`
93+ pub unsafe fn byte_at ( & self , offset : usize ) -> u8 {
94+ unsafe { BNGetDataBufferByte ( self . 0 , offset) }
95+ }
96+
97+ /// Set the value of the byte at `offset`
98+ pub unsafe fn set_byte_at ( & mut self , offset : usize , byte : u8 ) {
99+ unsafe { BNSetDataBufferByte ( self . 0 , offset, byte) }
100+ }
101+
46102 pub fn set_data ( & mut self , data : & [ u8 ] ) {
47103 unsafe {
48104 BNSetDataBufferContents (
@@ -53,12 +109,48 @@ impl DataBuffer {
53109 }
54110 }
55111
112+ pub fn to_escaped_string ( & self , null_terminates : bool ) -> BnString {
113+ unsafe { BnString :: from_raw ( BNDataBufferToEscapedString ( self . 0 , null_terminates) ) }
114+ }
115+
116+ pub fn from_escaped_string ( value : & BnString ) -> Self {
117+ Self ( unsafe { BNDecodeEscapedString ( value. as_raw ( ) ) } )
118+ }
119+
120+ pub fn to_base64 ( & self ) -> BnString {
121+ unsafe { BnString :: from_raw ( BNDataBufferToBase64 ( self . 0 ) ) }
122+ }
123+
124+ pub fn from_base64 ( value : & BnString ) -> Self {
125+ Self ( unsafe { BNDecodeBase64 ( value. as_raw ( ) ) } )
126+ }
127+
128+ pub fn zlib_compress ( & self ) -> Self {
129+ Self ( unsafe { BNZlibCompress ( self . 0 ) } )
130+ }
131+
132+ pub fn zlib_decompress ( & self ) -> Self {
133+ Self ( unsafe { BNZlibDecompress ( self . 0 ) } )
134+ }
135+
136+ pub fn lzma_decompress ( & self ) -> Self {
137+ Self ( unsafe { BNLzmaDecompress ( self . 0 ) } )
138+ }
139+
140+ pub fn lzma2_decompress ( & self ) -> Self {
141+ Self ( unsafe { BNLzma2Decompress ( self . 0 ) } )
142+ }
143+
144+ pub fn xz_decompress ( & self ) -> Self {
145+ Self ( unsafe { BNXzDecompress ( self . 0 ) } )
146+ }
147+
56148 pub fn len ( & self ) -> usize {
57149 unsafe { BNGetDataBufferLength ( self . 0 ) }
58150 }
59151
60152 pub fn is_empty ( & self ) -> bool {
61- unsafe { BNGetDataBufferLength ( self . 0 ) == 0 }
153+ self . len ( ) == 0
62154 }
63155
64156 pub fn new ( data : & [ u8 ] ) -> Result < Self , ( ) > {
@@ -71,19 +163,16 @@ impl DataBuffer {
71163 }
72164}
73165
74- // TODO : delete this
75166impl Default for DataBuffer {
76167 fn default ( ) -> Self {
77- DataBuffer :: from_raw ( ptr :: null_mut ( ) )
168+ Self ( unsafe { BNCreateDataBuffer ( [ ] . as_ptr ( ) as * const c_void , 0 ) } )
78169 }
79170}
80171
81172impl Drop for DataBuffer {
82173 fn drop ( & mut self ) {
83- if !self . 0 . is_null ( ) {
84- unsafe {
85- BNFreeDataBuffer ( self . 0 ) ;
86- }
174+ unsafe {
175+ BNFreeDataBuffer ( self . 0 ) ;
87176 }
88177 }
89178}
@@ -93,3 +182,152 @@ impl Clone for DataBuffer {
93182 Self :: from_raw ( unsafe { BNDuplicateDataBuffer ( self . 0 ) } )
94183 }
95184}
185+
186+ impl TryFrom < & [ u8 ] > for DataBuffer {
187+ type Error = ( ) ;
188+
189+ fn try_from ( value : & [ u8 ] ) -> Result < Self , Self :: Error > {
190+ DataBuffer :: new ( value)
191+ }
192+ }
193+
194+ impl AsRef < [ u8 ] > for DataBuffer {
195+ fn as_ref ( & self ) -> & [ u8 ] {
196+ self . get_data ( )
197+ }
198+ }
199+
200+ impl std:: borrow:: Borrow < [ u8 ] > for DataBuffer {
201+ fn borrow ( & self ) -> & [ u8 ] {
202+ self . as_ref ( )
203+ }
204+ }
205+
206+ macro_rules! data_buffer_index {
207+ ( $range: ty, $output: ty) => {
208+ impl std:: ops:: Index <$range> for DataBuffer {
209+ type Output = $output;
210+
211+ fn index( & self , index: $range) -> & Self :: Output {
212+ & self . get_data( ) [ index]
213+ }
214+ }
215+ } ;
216+ }
217+
218+ data_buffer_index ! ( usize , u8 ) ;
219+ data_buffer_index ! ( std:: ops:: Range <usize >, [ u8 ] ) ;
220+ data_buffer_index ! ( std:: ops:: RangeInclusive <usize >, [ u8 ] ) ;
221+ data_buffer_index ! ( std:: ops:: RangeTo <usize >, [ u8 ] ) ;
222+ data_buffer_index ! ( std:: ops:: RangeFull , [ u8 ] ) ;
223+
224+ impl PartialEq for DataBuffer {
225+ fn eq ( & self , other : & Self ) -> bool {
226+ self . as_ref ( ) == other. as_ref ( )
227+ }
228+ }
229+ impl Eq for DataBuffer { }
230+
231+ impl PartialOrd for DataBuffer {
232+ fn partial_cmp ( & self , other : & Self ) -> Option < std:: cmp:: Ordering > {
233+ Some ( self . as_ref ( ) . cmp ( other. as_ref ( ) ) )
234+ }
235+ }
236+
237+ impl Ord for DataBuffer {
238+ fn cmp ( & self , other : & Self ) -> std:: cmp:: Ordering {
239+ self . as_ref ( ) . cmp ( other. as_ref ( ) )
240+ }
241+ }
242+
243+ #[ cfg( test) ]
244+ mod test {
245+ use super :: DataBuffer ;
246+
247+ const DUMMY_DATA_0 : & [ u8 ] = b"0123456789\x00 \x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x09 \xFF " ;
248+ const DUMMY_DATA_1 : & [ u8 ] = b"qwertyuiopasdfghjkl\xE7 zxcvbnm\x00 \x01 \x00 " ;
249+
250+ #[ test]
251+ fn get_slice ( ) {
252+ let data = DataBuffer :: new ( DUMMY_DATA_0 ) . unwrap ( ) ;
253+ let slice = data. get_slice ( 9 , 10 ) . unwrap ( ) ;
254+ assert_eq ! ( slice. get_data( ) , & DUMMY_DATA_0 [ 9 ..19 ] ) ;
255+ }
256+
257+ #[ test]
258+ fn set_len_write ( ) {
259+ let mut data = DataBuffer :: default ( ) ;
260+ assert_eq ! ( data. get_data( ) , & [ ] ) ;
261+ unsafe { data. set_len ( DUMMY_DATA_0 . len ( ) ) } ;
262+ assert_eq ! ( data. len( ) , DUMMY_DATA_0 . len( ) ) ;
263+ let mut contents = DUMMY_DATA_0 . to_vec ( ) ;
264+ data. set_data ( & contents) ;
265+ // modify the orinal contents, to make sure DataBuffer copied the data
266+ // and is not using the original pointer
267+ contents. as_mut_slice ( ) . fill ( 0x55 ) ;
268+ drop ( contents) ;
269+ assert_eq ! ( data. get_data( ) , & DUMMY_DATA_0 [ ..] ) ;
270+
271+ // make sure the new len truncate the original data
272+ unsafe { data. set_len ( 13 ) } ;
273+ assert_eq ! ( data. get_data( ) , & DUMMY_DATA_0 [ ..13 ] ) ;
274+
275+ data. clear ( ) ;
276+ assert_eq ! ( data. get_data( ) , & [ ] ) ;
277+ }
278+
279+ #[ test]
280+ fn assign_append ( ) {
281+ let mut dst = DataBuffer :: new ( DUMMY_DATA_0 ) . unwrap ( ) ;
282+ let mut src = DataBuffer :: new ( DUMMY_DATA_1 ) . unwrap ( ) ;
283+ DataBuffer :: assign ( & mut dst, & src) ;
284+
285+ assert_eq ! ( dst. get_data( ) , DUMMY_DATA_1 ) ;
286+ assert_eq ! ( src. get_data( ) , DUMMY_DATA_1 ) ;
287+ // overwrite the src, to make sure that src is copied to dst, and not
288+ // moved into it
289+ src. set_data ( DUMMY_DATA_0 ) ;
290+ assert_eq ! ( dst. get_data( ) , DUMMY_DATA_1 ) ;
291+ assert_eq ! ( src. get_data( ) , DUMMY_DATA_0 ) ;
292+
293+ DataBuffer :: append ( & mut dst, & src) ;
294+ let result: Vec < _ > = DUMMY_DATA_1 . iter ( ) . chain ( DUMMY_DATA_0 ) . copied ( ) . collect ( ) ;
295+ assert_eq ! ( dst. get_data( ) , & result) ;
296+
297+ assert_eq ! ( src. get_data( ) , DUMMY_DATA_0 ) ;
298+ src. set_data ( DUMMY_DATA_1 ) ;
299+ assert_eq ! ( src. get_data( ) , DUMMY_DATA_1 ) ;
300+ assert_eq ! ( dst. get_data( ) , & result) ;
301+ }
302+
303+ #[ test]
304+ fn to_from_formats ( ) {
305+ let data = DataBuffer :: new ( DUMMY_DATA_0 ) . unwrap ( ) ;
306+ let escaped = data. to_escaped_string ( false ) ;
307+ let unescaped = DataBuffer :: from_escaped_string ( & escaped) ;
308+ drop ( escaped) ;
309+ let escaped_part = data. to_escaped_string ( true ) ;
310+ let unescaped_part = DataBuffer :: from_escaped_string ( & escaped_part) ;
311+ drop ( escaped_part) ;
312+
313+ let part = & DUMMY_DATA_0 [ 0 ..DUMMY_DATA_0
314+ . iter ( )
315+ . position ( |x| * x == 0 )
316+ . unwrap_or ( DUMMY_DATA_0 . len ( ) ) ] ;
317+ assert_eq ! ( data. get_data( ) , DUMMY_DATA_0 ) ;
318+ assert_eq ! ( unescaped. get_data( ) , DUMMY_DATA_0 ) ;
319+ assert_eq ! ( unescaped_part. get_data( ) , part) ;
320+
321+ let escaped = data. to_base64 ( ) ;
322+ let unescaped = DataBuffer :: from_base64 ( & escaped) ;
323+ drop ( escaped) ;
324+ assert_eq ! ( data. get_data( ) , DUMMY_DATA_0 ) ;
325+ assert_eq ! ( unescaped. get_data( ) , DUMMY_DATA_0 ) ;
326+
327+ let compressed = data. zlib_compress ( ) ;
328+ let decompressed = compressed. zlib_decompress ( ) ;
329+ drop ( compressed) ;
330+ assert_eq ! ( data. get_data( ) , DUMMY_DATA_0 ) ;
331+ assert_eq ! ( decompressed. get_data( ) , DUMMY_DATA_0 ) ;
332+ }
333+ }
0 commit comments