@@ -167,6 +167,46 @@ impl CStr {
167
167
pub const fn as_bytes_with_nul ( & self ) -> & [ u8 ] {
168
168
& self . 0
169
169
}
170
+
171
+ /// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8.
172
+ ///
173
+ /// If the contents of the [`CStr`] are valid UTF-8 data, this
174
+ /// function will return the corresponding [`&str`] slice. Otherwise,
175
+ /// it will return an error with details of where UTF-8 validation failed.
176
+ ///
177
+ /// # Examples
178
+ ///
179
+ /// ```
180
+ /// # use kernel::str::CStr;
181
+ /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
182
+ /// assert_eq!(cstr.to_str(), Ok("foo"));
183
+ /// ```
184
+ #[ inline]
185
+ pub fn to_str ( & self ) -> Result < & str , core:: str:: Utf8Error > {
186
+ core:: str:: from_utf8 ( self . as_bytes ( ) )
187
+ }
188
+
189
+ /// Unsafely convert this [`CStr`] into a [`&str`], without checking for
190
+ /// valid UTF-8.
191
+ ///
192
+ /// # Safety
193
+ ///
194
+ /// The contents must be valid UTF-8.
195
+ ///
196
+ /// # Examples
197
+ ///
198
+ /// ```
199
+ /// # use kernel::c_str;
200
+ /// # use kernel::str::CStr;
201
+ /// // SAFETY: String literals are guaranteed to be valid UTF-8
202
+ /// // by the Rust compiler.
203
+ /// let bar = c_str!("ツ");
204
+ /// assert_eq!(unsafe { bar.as_str_unchecked() }, "ツ");
205
+ /// ```
206
+ #[ inline]
207
+ pub unsafe fn as_str_unchecked ( & self ) -> & str {
208
+ unsafe { core:: str:: from_utf8_unchecked ( self . as_bytes ( ) ) }
209
+ }
170
210
}
171
211
172
212
impl AsRef < BStr > for CStr {
@@ -251,3 +291,32 @@ macro_rules! c_str {
251
291
C
252
292
} } ;
253
293
}
294
+
295
+ #[ cfg( test) ]
296
+ mod tests {
297
+ use super :: * ;
298
+
299
+ #[ test]
300
+ fn test_cstr_to_str ( ) {
301
+ let good_bytes = b"\xf0 \x9f \xa6 \x80 \0 " ;
302
+ let checked_cstr = CStr :: from_bytes_with_nul ( good_bytes) . unwrap ( ) ;
303
+ let checked_str = checked_cstr. to_str ( ) . unwrap ( ) ;
304
+ assert_eq ! ( checked_str, "🦀" ) ;
305
+ }
306
+
307
+ #[ test]
308
+ #[ should_panic]
309
+ fn test_cstr_to_str_panic ( ) {
310
+ let bad_bytes = b"\xc3 \x28 \0 " ;
311
+ let checked_cstr = CStr :: from_bytes_with_nul ( bad_bytes) . unwrap ( ) ;
312
+ checked_cstr. to_str ( ) . unwrap ( ) ;
313
+ }
314
+
315
+ #[ test]
316
+ fn test_cstr_as_str_unchecked ( ) {
317
+ let good_bytes = b"\xf0 \x9f \x90 \xA7 \0 " ;
318
+ let checked_cstr = CStr :: from_bytes_with_nul ( good_bytes) . unwrap ( ) ;
319
+ let unchecked_str = unsafe { checked_cstr. as_str_unchecked ( ) } ;
320
+ assert_eq ! ( unchecked_str, "🐧" ) ;
321
+ }
322
+ }
0 commit comments