@@ -22,6 +22,9 @@ pub enum FromSliceWithNulError {
22
22
23
23
/// The slice was not null-terminated
24
24
NotNulTerminated ,
25
+
26
+ /// The buffer is broken. For example, not a multiple of 2 bytes.
27
+ BrokenBuffer ,
25
28
}
26
29
27
30
/// Error returned by [`CStr16::from_unaligned_slice`].
@@ -211,10 +214,21 @@ impl CStr16 {
211
214
Self :: from_u16_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len + 1 ) )
212
215
}
213
216
214
- /// Creates a C string wrapper from a u16 slice
215
- ///
216
- /// Since not every u16 value is a valid UCS-2 code point, this function
217
- /// must do a bit more validity checking than CStr::from_bytes_with_nul
217
+ /// Creates a `&CStr16` from a u8 slice, if the slice contains exactly
218
+ /// one terminating null-byte and all chars are valid UCS-2 chars.
219
+ pub fn from_u8_with_nul ( slice : & [ u8 ] ) -> Result < & Self , FromSliceWithNulError > {
220
+ if slice. is_empty ( ) {
221
+ return Err ( FromSliceWithNulError :: NotNulTerminated ) ;
222
+ }
223
+ if slice. len ( ) % 2 != 0 {
224
+ return Err ( FromSliceWithNulError :: BrokenBuffer ) ;
225
+ }
226
+ let slice = unsafe { slice:: from_raw_parts ( slice. as_ptr ( ) . cast :: < u16 > ( ) , slice. len ( ) / 2 ) } ;
227
+ Self :: from_u16_with_nul ( slice)
228
+ }
229
+
230
+ /// Creates a `&CStr16` from a u16 slice, if the slice contains exactly
231
+ /// one terminating null-byte and all chars are valid UCS-2 chars.
218
232
pub fn from_u16_with_nul ( codes : & [ u16 ] ) -> Result < & Self , FromSliceWithNulError > {
219
233
for ( pos, & code) in codes. iter ( ) . enumerate ( ) {
220
234
match code. try_into ( ) {
@@ -234,7 +248,7 @@ impl CStr16 {
234
248
Err ( FromSliceWithNulError :: NotNulTerminated )
235
249
}
236
250
237
- /// Unsafely creates a C string wrapper from a u16 slice.
251
+ /// Unsafely creates a `&CStr16` from a u16 slice.
238
252
///
239
253
/// # Safety
240
254
///
@@ -287,11 +301,13 @@ impl CStr16 {
287
301
Self :: from_u16_with_nul ( & buf[ ..index + 1 ] ) . map_err ( |err| match err {
288
302
FromSliceWithNulError :: InvalidChar ( p) => FromStrWithBufError :: InvalidChar ( p) ,
289
303
FromSliceWithNulError :: InteriorNul ( p) => FromStrWithBufError :: InteriorNul ( p) ,
290
- FromSliceWithNulError :: NotNulTerminated => unreachable ! ( ) ,
304
+ FromSliceWithNulError :: NotNulTerminated | FromSliceWithNulError :: BrokenBuffer => {
305
+ unreachable ! ( )
306
+ }
291
307
} )
292
308
}
293
309
294
- /// Create a [` CStr16`] from an [`UnalignedSlice`] using an aligned
310
+ /// Create a `& CStr16` from an [`UnalignedSlice`] using an aligned
295
311
/// buffer for storage. The lifetime of the output is tied to `buf`,
296
312
/// not `src`.
297
313
pub fn from_unaligned_slice < ' buf > (
@@ -313,6 +329,7 @@ impl CStr16 {
313
329
FromSliceWithNulError :: InvalidChar ( v) => UnalignedCStr16Error :: InvalidChar ( v) ,
314
330
FromSliceWithNulError :: InteriorNul ( v) => UnalignedCStr16Error :: InteriorNul ( v) ,
315
331
FromSliceWithNulError :: NotNulTerminated => UnalignedCStr16Error :: NotNulTerminated ,
332
+ FromSliceWithNulError :: BrokenBuffer => UnalignedCStr16Error :: BufferTooSmall ,
316
333
} )
317
334
}
318
335
@@ -562,6 +579,13 @@ mod tests {
562
579
assert_eq ! ( <CStr8 as Borrow <[ u8 ] >>:: borrow( string) , & [ b'a' , 0 ] ) ;
563
580
}
564
581
582
+ #[ test]
583
+ fn test_cstr16_from_slice ( ) {
584
+ let s1 = CStr16 :: from_u8_with_nul ( & [ 65 , 0 , 66 , 0 , 67 , 0 , 0 , 0 ] ) . unwrap ( ) ;
585
+ let s2 = CStr16 :: from_u16_with_nul ( & [ 65 , 66 , 67 , 0 ] ) . unwrap ( ) ;
586
+ assert_eq ! ( s1, s2)
587
+ }
588
+
565
589
#[ test]
566
590
fn test_cstr16_num_bytes ( ) {
567
591
let s = CStr16 :: from_u16_with_nul ( & [ 65 , 66 , 67 , 0 ] ) . unwrap ( ) ;
0 commit comments