12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- use core:: fmt:: Write ;
16
- use util:: c_types:: { c_char, c_uchar} ;
15
+ use util:: c_types:: c_uchar;
17
16
18
17
/// Zero a buffer using volatile writes. Accepts null-ptr and 0-length buffers and does nothing.
19
18
///
@@ -26,29 +25,22 @@ pub extern "C" fn rust_util_zero(mut dst: BytesMut) {
26
25
util:: zero ( dst. as_mut ( ) )
27
26
}
28
27
29
- #[ no_mangle]
30
- pub extern "C" fn rust_util_u64_be ( v : u64 , mut dst : BytesMut ) {
31
- dst. as_mut ( ) . copy_from_slice ( & v. to_be_bytes ( ) )
32
- }
33
-
34
28
/// Convert bytes to hex representation
35
29
///
36
30
/// * `buf` - bytes to convert to hex.
37
31
/// * `out` - hex will be written here. out len must be at least 2*buf.len+1.
38
32
#[ no_mangle]
39
- pub extern "C" fn rust_util_uint8_to_hex ( buf : Bytes , mut out : CStrMut ) {
40
- let min_len = buf. len * 2 ;
41
- match out. write ( min_len, |out| {
42
- // Avoid .unwrap() here until the following compiler regression is fixed:
43
- // https://github.com/rust-lang/rust/issues/83925
44
- match hex:: encode_to_slice ( & buf, out) {
45
- Ok ( ( ) ) => { }
46
- Err ( err) => panic ! ( "{:?}" , err) ,
47
- }
48
- } ) {
33
+ pub extern "C" fn rust_util_uint8_to_hex ( buf : Bytes , mut out : BytesMut ) {
34
+ let bytes = buf. as_ref ( ) ;
35
+ let hexlen = bytes. len ( ) * 2 ;
36
+ // Avoid .unwrap() here until the following compiler regression is fixed:
37
+ // https://github.com/rust-lang/rust/issues/83925
38
+ match hex:: encode_to_slice ( bytes, & mut out. as_mut ( ) [ ..hexlen] ) {
49
39
Ok ( ( ) ) => { }
50
- Err ( _ ) => panic ! ( "couldn't write to buffer" ) ,
40
+ Err ( err ) => panic ! ( "{:?}" , err ) ,
51
41
}
42
+ // Null terminator.
43
+ out. as_mut ( ) [ hexlen] = 0 ;
52
44
}
53
45
54
46
#[ repr( C ) ]
@@ -105,133 +97,6 @@ impl AsMut<[u8]> for BytesMut {
105
97
}
106
98
}
107
99
108
- /// CStr is a null-terminated string. Null pointers are interpreted as empty strings.
109
- #[ repr( C ) ]
110
- pub struct CStr {
111
- buf : * const c_char ,
112
- len : usize ,
113
- }
114
-
115
- impl CStr {
116
- /// Create a CStr from a null-terminated string or null pointer. Unsafe because it will read
117
- /// until it finds a null character.
118
- pub unsafe fn new ( buf : * const c_char ) -> Self {
119
- if buf. is_null ( ) {
120
- CStr {
121
- buf : core:: ptr:: NonNull :: dangling ( ) . as_ptr ( ) ,
122
- len : 0 ,
123
- }
124
- } else {
125
- let mut len = 0 ;
126
- let mut b = buf;
127
- while b. read ( ) != 0 {
128
- len += 1 ;
129
- b = b. offset ( 1 ) ;
130
- }
131
- CStr { buf, len }
132
- }
133
- }
134
- }
135
-
136
- impl AsRef < str > for CStr {
137
- fn as_ref ( & self ) -> & str {
138
- unsafe { core:: str:: from_utf8_unchecked ( core:: slice:: from_raw_parts ( self . buf , self . len ) ) }
139
- }
140
- }
141
-
142
- /// CStrMut is a "growable" container which keeps track of some array allocated by C with a length
143
- /// and a capacity state. It always contains a null-terminated string. The string (excluding null
144
- /// terminator) can therefore be maximally `capacity-1` long.
145
- #[ repr( C ) ]
146
- pub struct CStrMut {
147
- buf : * mut c_char ,
148
- len : usize ,
149
- cap : usize ,
150
- }
151
-
152
- impl CStrMut {
153
- /// Create a new growable string with capacity `cap`. Only allowed for non-null pointers with
154
- /// length or null pointers with 0 length due to limitation in `core::slice`. Unsafe because it
155
- /// will read until it finds a null character.
156
- pub unsafe fn new ( buf : * mut c_char , cap : usize ) -> Self {
157
- let mut len = 0 ;
158
- let mut buf = buf;
159
- if buf. is_null ( ) {
160
- if cap != 0 {
161
- panic ! ( "Null pointer can't have capacity" ) ;
162
- }
163
- buf = core:: ptr:: NonNull :: dangling ( ) . as_ptr ( ) ;
164
- } else {
165
- let mut b = buf;
166
- while b. read ( ) != 0 {
167
- len += 1 ;
168
- b = b. offset ( 1 ) ;
169
- if len == cap {
170
- panic ! ( "CStrMut not null terminated" ) ;
171
- }
172
- }
173
- }
174
-
175
- CStrMut { buf, len, cap }
176
- }
177
-
178
- /// Provide a mutable slice to an unused range of the buffer. The provided function `f` must
179
- /// fill the requested buffer with utf-8 valid characters and it must not write a null
180
- /// character in the buffer.
181
- ///
182
- /// # Panics
183
- ///
184
- /// This function returns an error in case the provided buffer contains NULL or non-valid utf-8
185
- /// characters after function `f` is applied. It will also return an error if more bytes are
186
- /// requested then are available.
187
- pub fn write < F > ( & mut self , req : usize , f : F ) -> Result < ( ) , core:: fmt:: Error >
188
- where
189
- F : FnOnce ( & mut [ u8 ] ) ,
190
- {
191
- // Must be room for requested amount of bytes and null terminator.
192
- if self . cap - self . len < req + 1 {
193
- // Not enough bytes left in buffer
194
- return Err ( core:: fmt:: Error ) ;
195
- }
196
- let len = self . len ;
197
- let slice = unsafe { self . as_bytes_mut ( ) } ;
198
- let slice = & mut slice[ len..len + req + 1 ] ;
199
- let write_slice = & mut slice[ 0 ..req] ;
200
- f ( write_slice) ;
201
- if write_slice. iter ( ) . any ( |& c| c == 0 ) {
202
- // null terminated strings can't contain null
203
- return Err ( core:: fmt:: Error ) ;
204
- }
205
- if core:: str:: from_utf8 ( write_slice) . is_err ( ) {
206
- // strings must be valid utf-8
207
- return Err ( core:: fmt:: Error ) ;
208
- }
209
- slice[ req] = 0 ;
210
- self . len += req;
211
- Ok ( ( ) )
212
- }
213
-
214
- /// Get slice of underlying byte array. Unsafe because you have to ensure that length is up to
215
- /// date and that there is a null character at `buf[len]`.
216
- pub unsafe fn as_bytes_mut ( & mut self ) -> & mut [ u8 ] {
217
- core:: slice:: from_raw_parts_mut ( self . buf , self . cap )
218
- }
219
- }
220
-
221
- impl AsRef < str > for CStrMut {
222
- fn as_ref ( & self ) -> & str {
223
- unsafe { core:: str:: from_utf8_unchecked ( core:: slice:: from_raw_parts ( self . buf , self . len ) ) }
224
- }
225
- }
226
-
227
- impl core:: fmt:: Write for CStrMut {
228
- fn write_str ( & mut self , s : & str ) -> Result < ( ) , core:: fmt:: Error > {
229
- self . write ( s. len ( ) , |buf| {
230
- buf. copy_from_slice ( s. as_bytes ( ) ) ;
231
- } )
232
- }
233
- }
234
-
235
100
/// Convert buffer to slice
236
101
///
237
102
/// * `buf` - Must be a valid pointer to an array of bytes
@@ -246,41 +111,24 @@ pub extern "C" fn rust_util_bytes(buf: *const c_uchar, len: usize) -> Bytes {
246
111
/// * `buf` - Must be a valid pointer to an array of bytes
247
112
/// * `len` - Length of buffer, `buf[len-1]` must be a valid dereference
248
113
#[ no_mangle]
249
- pub extern "C" fn rust_util_bytes_mut ( buf : * mut c_uchar , len : usize ) -> BytesMut {
114
+ pub unsafe extern "C" fn rust_util_bytes_mut ( buf : * mut c_uchar , len : usize ) -> BytesMut {
250
115
BytesMut { buf, len }
251
116
}
252
117
253
- /// Convert buffer to str.
254
- ///
255
- /// * `buf` - Must be a valid pointer to a null terminated array of bytes.
256
- #[ no_mangle]
257
- pub unsafe extern "C" fn rust_util_cstr ( buf : * const c_char ) -> CStr {
258
- CStr :: new ( buf)
259
- }
260
-
261
- /// Convert buffer to mutable str. The whole buffer is considered empty from start.
262
- ///
263
- /// * `buf` - Must be a valid pointer to an array of bytes
264
- /// * `cap` - Length of buffer, `buf_ptr[cap-1]` must be a valid dereference
265
- #[ no_mangle]
266
- pub unsafe extern "C" fn rust_util_cstr_mut ( buf : * mut c_char , cap : usize ) -> CStrMut {
267
- if !buf. is_null ( ) {
268
- buf. write ( 0 ) ;
269
- }
270
- CStrMut :: new ( buf, cap)
271
- }
272
-
273
118
/// Base58Check-encode the input.
274
119
///
275
120
/// #Safety
276
121
/// buf and out must not be NULL and point to valid memory areas.
277
122
#[ no_mangle]
278
- pub unsafe extern "C" fn rust_base58_encode_check ( buf : Bytes , mut out : CStrMut ) -> bool {
123
+ pub unsafe extern "C" fn rust_base58_encode_check ( buf : Bytes , mut out : BytesMut ) -> bool {
279
124
if buf. len == 0 {
280
125
return false ;
281
126
}
282
127
let encoded = bs58:: encode ( buf. as_ref ( ) ) . with_check ( ) . into_string ( ) ;
283
- write ! ( & mut out, "{}" , encoded) . is_ok ( )
128
+ out. as_mut ( ) [ ..encoded. len ( ) ] . copy_from_slice ( encoded. as_bytes ( ) ) ;
129
+ // Null-terminator.
130
+ out. as_mut ( ) [ encoded. len ( ) ] = 0 ;
131
+ true
284
132
}
285
133
286
134
#[ cfg( test) ]
@@ -291,37 +139,28 @@ mod tests {
291
139
#[ test]
292
140
fn zeroing ( ) {
293
141
let mut buf = [ 1u8 , 2 , 3 , 4 ] ;
294
- rust_util_zero ( rust_util_bytes_mut ( buf. as_mut_ptr ( ) , buf. len ( ) - 1 ) ) ;
142
+ rust_util_zero ( unsafe { rust_util_bytes_mut ( buf. as_mut_ptr ( ) , buf. len ( ) - 1 ) } ) ;
295
143
assert_eq ! ( & buf[ ..] , & [ 0 , 0 , 0 , 4 ] ) ;
296
144
}
297
145
298
146
#[ test]
299
147
fn zeroing_empty ( ) {
300
148
let mut buf = [ ] ;
301
- rust_util_zero ( rust_util_bytes_mut ( buf. as_mut_ptr ( ) , 0 ) ) ;
149
+ rust_util_zero ( unsafe { rust_util_bytes_mut ( buf. as_mut_ptr ( ) , 0 ) } ) ;
302
150
}
303
151
304
152
#[ test]
305
153
fn zeroing_null ( ) {
306
- rust_util_zero ( rust_util_bytes_mut ( core:: ptr:: null_mut ( ) , 0 ) ) ;
307
- }
308
-
309
- #[ test]
310
- fn test_rust_util_cstr ( ) {
311
- let cstr = unsafe { rust_util_cstr ( b"\0 " . as_ptr ( ) ) } ;
312
- assert_eq ! ( cstr. as_ref( ) , "" ) ;
313
- assert_eq ! ( cstr. len, 0 ) ;
314
-
315
- let cstr = unsafe { rust_util_cstr ( b"foo\0 bar" . as_ptr ( ) ) } ;
316
- assert_eq ! ( cstr. as_ref( ) , "foo" ) ;
317
- assert_eq ! ( cstr. len, 3 ) ;
154
+ rust_util_zero ( unsafe { rust_util_bytes_mut ( core:: ptr:: null_mut ( ) , 0 ) } ) ;
318
155
}
319
156
320
157
#[ test]
321
158
#[ should_panic]
322
159
fn create_invalid_bytes_mut ( ) {
323
160
// Calling `as_mut()` will panic because it tries to create an invalid rust slice.
324
- rust_util_bytes_mut ( core:: ptr:: null_mut ( ) , 1 ) . as_mut ( ) ;
161
+ unsafe {
162
+ rust_util_bytes_mut ( core:: ptr:: null_mut ( ) , 1 ) . as_mut ( ) ;
163
+ }
325
164
}
326
165
327
166
#[ test]
@@ -332,80 +171,18 @@ mod tests {
332
171
}
333
172
334
173
#[ test]
335
- fn test_cstr_mut ( ) {
336
- let mut start = String :: from ( "foo\0 bar" ) ;
337
- let mut cstr_mut = unsafe { rust_util_cstr_mut ( start. as_mut_ptr ( ) , start. len ( ) ) } ;
338
- assert_eq ! ( cstr_mut. len, 0 ) ;
339
- assert_eq ! ( cstr_mut. as_ref( ) , "" ) ;
340
- cstr_mut. write ( 1 , |buf| buf[ 0 ] = b'g' ) . unwrap ( ) ;
341
- assert_eq ! ( cstr_mut. as_ref( ) , "g" ) ;
342
- }
343
-
344
- #[ test]
345
- fn test_cstr_mut_new ( ) {
346
- let mut start = String :: from ( "foo\0 bar" ) ;
347
- let mut cstr_mut = unsafe { CStrMut :: new ( start. as_mut_ptr ( ) , start. len ( ) ) } ;
348
- assert_eq ! ( cstr_mut. len, 3 ) ;
349
- assert_eq ! ( cstr_mut. as_ref( ) , "foo" ) ;
350
- cstr_mut. write ( 1 , |buf| buf[ 0 ] = b'g' ) . unwrap ( ) ;
351
- assert_eq ! ( cstr_mut. as_ref( ) , "foog" ) ;
352
- }
353
-
354
- #[ test]
355
- #[ should_panic]
356
- fn test_invalid_cstr_mut ( ) {
357
- let mut buf = [ 1 , 2 , 3 ] ;
358
- let cstr_mut = unsafe { CStrMut :: new ( buf. as_mut_ptr ( ) , buf. len ( ) ) } ;
359
- // panics as there is no null terminator.
360
- cstr_mut. as_ref ( ) ;
361
- }
362
-
363
- #[ test]
364
- fn test_invalid_cstr_mut_write_null ( ) {
365
- let mut s = String :: from ( "abc\0 xxx" ) ;
366
- let mut cstr_mut = unsafe { CStrMut :: new ( s. as_mut_ptr ( ) , s. len ( ) ) } ;
367
- assert ! ( cstr_mut. write( 1 , |buf| buf[ 0 ] = 0 ) . is_err( ) ) ;
368
- }
369
-
370
- #[ test]
371
- fn test_invalid_cstr_mut_out_of_buffer ( ) {
372
- let mut s = String :: from ( "abc\0 " ) ;
373
- let mut cstr_mut = unsafe { CStrMut :: new ( s. as_mut_ptr ( ) , s. len ( ) ) } ;
374
- assert ! ( cstr_mut. write( 1 , |buf| buf[ 0 ] = b'd' ) . is_err( ) ) ;
375
- }
376
-
377
- #[ test]
378
- fn test_cstr_mut_write ( ) {
379
- let mut buf = vec ! [ 0 ; 9 ] ;
380
- let mut cstr_mut = unsafe { CStrMut :: new ( buf. as_mut_ptr ( ) , buf. len ( ) ) } ;
381
- use std:: fmt:: Write ;
382
- assert ! ( write!( & mut cstr_mut, "test" ) . is_ok( ) ) ;
383
- assert ! ( buf. starts_with( b"test\0 " ) ) ;
384
- assert ! ( write!( & mut cstr_mut, " foo" ) . is_ok( ) ) ;
385
- assert ! ( buf. starts_with( b"test foo\0 " ) ) ;
386
- }
387
-
388
- #[ test]
389
- fn test_cstr_mut_write_too_much ( ) {
390
- let mut buf = vec ! [ 0 ; 9 ] ;
391
- let mut cstr_mut = unsafe { CStrMut :: new ( buf. as_mut_ptr ( ) , buf. len ( ) ) } ;
392
- use std:: fmt:: Write ;
393
- assert ! ( write!( & mut cstr_mut, "test foo " ) . is_err( ) ) ;
394
- }
395
-
396
- #[ test]
397
- fn u8_to_hexing ( ) {
398
- let buf = [ 1u8 , 2 , 3 , 14 , 15 , 255 , 1 ] ;
399
- let mut string = String :: from ( "\0 xxxxxxxxxxxxx" ) ;
400
- rust_util_uint8_to_hex ( rust_util_bytes ( buf. as_ptr ( ) , buf. len ( ) - 1 ) , unsafe {
401
- rust_util_cstr_mut ( string. as_mut_ptr ( ) , string. len ( ) - 1 )
174
+ fn test_uint8_to_hex ( ) {
175
+ let buf = [ 1u8 , 2 , 3 , 14 , 15 , 255 ] ;
176
+ let mut string = String :: from ( "xxxxxxxxxxxxx" ) ;
177
+ rust_util_uint8_to_hex ( rust_util_bytes ( buf. as_ptr ( ) , buf. len ( ) ) , unsafe {
178
+ rust_util_bytes_mut ( string. as_mut_ptr ( ) , string. len ( ) )
402
179
} ) ;
403
- assert_eq ! ( string, "0102030e0fff\0 x " ) ;
180
+ assert_eq ! ( string, "0102030e0fff\0 " ) ;
404
181
405
182
// Bigger buffer also works.
406
183
let mut string = String :: from ( "\0 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ) ;
407
- rust_util_uint8_to_hex ( rust_util_bytes ( buf. as_ptr ( ) , buf. len ( ) - 1 ) , unsafe {
408
- rust_util_cstr_mut ( string. as_mut_ptr ( ) , string. len ( ) )
184
+ rust_util_uint8_to_hex ( rust_util_bytes ( buf. as_ptr ( ) , buf. len ( ) ) , unsafe {
185
+ rust_util_bytes_mut ( string. as_mut_ptr ( ) , string. len ( ) )
409
186
} ) ;
410
187
assert_eq ! ( string, "0102030e0fff\0 xxxxxxxxxxxxxxxxxxxxxxx" ) ;
411
188
}
@@ -417,12 +194,10 @@ mod tests {
417
194
assert ! ( unsafe {
418
195
rust_base58_encode_check(
419
196
rust_util_bytes( buf. as_ptr( ) , buf. len( ) ) ,
420
- rust_util_cstr_mut ( result_buf. as_mut_ptr( ) , result_buf. len( ) ) ,
197
+ rust_util_bytes_mut ( result_buf. as_mut_ptr( ) , result_buf. len( ) ) ,
421
198
)
422
199
} ) ;
423
- assert_eq ! (
424
- ( unsafe { rust_util_cstr( result_buf. as_ptr( ) ) } ) . as_ref( ) ,
425
- "LUC1eAJa5jW"
426
- ) ;
200
+ let expected = b"LUC1eAJa5jW\0 " ;
201
+ assert_eq ! ( & result_buf[ ..expected. len( ) ] , expected) ;
427
202
}
428
203
}
0 commit comments