1 use crate::cmp::Ordering; 2 use crate::error::Error; 3 use crate::ffi::c_char; 4 use crate::fmt; 5 use crate::intrinsics; 6 use crate::ops; 7 use crate::slice; 8 use crate::slice::memchr; 9 use crate::str; 10 11 /// Representation of a borrowed C string. 12 /// 13 /// This type represents a borrowed reference to a nul-terminated 14 /// array of bytes. It can be constructed safely from a <code>&[[u8]]</code> 15 /// slice, or unsafely from a raw `*const c_char`. It can then be 16 /// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or 17 /// into an owned [`CString`]. 18 /// 19 /// `&CStr` is to [`CString`] as <code>&[str]</code> is to [`String`]: the former 20 /// in each pair are borrowed references; the latter are owned 21 /// strings. 22 /// 23 /// Note that this structure is **not** `repr(C)` and is not recommended to be 24 /// placed in the signatures of FFI functions. Instead, safe wrappers of FFI 25 /// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide 26 /// a safe interface to other consumers. 27 /// 28 /// [`CString`]: ../../std/ffi/struct.CString.html 29 /// [`String`]: ../../std/string/struct.String.html 30 /// 31 /// # Examples 32 /// 33 /// Inspecting a foreign C string: 34 /// 35 /// ```ignore (extern-declaration) 36 /// use std::ffi::CStr; 37 /// use std::os::raw::c_char; 38 /// 39 /// extern "C" { fn my_string() -> *const c_char; } 40 /// 41 /// unsafe { 42 /// let slice = CStr::from_ptr(my_string()); 43 /// println!("string buffer size without nul terminator: {}", slice.to_bytes().len()); 44 /// } 45 /// ``` 46 /// 47 /// Passing a Rust-originating C string: 48 /// 49 /// ```ignore (extern-declaration) 50 /// use std::ffi::{CString, CStr}; 51 /// use std::os::raw::c_char; 52 /// 53 /// fn work(data: &CStr) { 54 /// extern "C" { fn work_with(data: *const c_char); } 55 /// 56 /// unsafe { work_with(data.as_ptr()) } 57 /// } 58 /// 59 /// let s = CString::new("data data data data").expect("CString::new failed"); 60 /// work(&s); 61 /// ``` 62 /// 63 /// Converting a foreign C string into a Rust `String`: 64 /// 65 /// ```ignore (extern-declaration) 66 /// use std::ffi::CStr; 67 /// use std::os::raw::c_char; 68 /// 69 /// extern "C" { fn my_string() -> *const c_char; } 70 /// 71 /// fn my_string_safe() -> String { 72 /// let cstr = unsafe { CStr::from_ptr(my_string()) }; 73 /// // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation 74 /// String::from_utf8_lossy(cstr.to_bytes()).to_string() 75 /// } 76 /// 77 /// println!("string: {}", my_string_safe()); 78 /// ``` 79 /// 80 /// [str]: prim@str "str" 81 #[derive(Hash)] 82 #[stable(feature = "core_c_str", since = "1.64.0")] 83 #[rustc_has_incoherent_inherent_impls] 84 #[lang = "CStr"] 85 // FIXME: 86 // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies 87 // on `CStr` being layout-compatible with `[u8]`. 88 // When attribute privacy is implemented, `CStr` should be annotated as `#[repr(transparent)]`. 89 // Anyway, `CStr` representation and layout are considered implementation detail, are 90 // not documented and must not be relied upon. 91 pub struct CStr { 92 // FIXME: this should not be represented with a DST slice but rather with 93 // just a raw `c_char` along with some form of marker to make 94 // this an unsized type. Essentially `sizeof(&CStr)` should be the 95 // same as `sizeof(&c_char)` but `CStr` should be an unsized type. 96 inner: [c_char], 97 } 98 99 /// An error indicating that a nul byte was not in the expected position. 100 /// 101 /// The slice used to create a [`CStr`] must have one and only one nul byte, 102 /// positioned at the end. 103 /// 104 /// This error is created by the [`CStr::from_bytes_with_nul`] method. 105 /// See its documentation for more. 106 /// 107 /// # Examples 108 /// 109 /// ``` 110 /// use std::ffi::{CStr, FromBytesWithNulError}; 111 /// 112 /// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err(); 113 /// ``` 114 #[derive(Clone, PartialEq, Eq, Debug)] 115 #[stable(feature = "core_c_str", since = "1.64.0")] 116 pub struct FromBytesWithNulError { 117 kind: FromBytesWithNulErrorKind, 118 } 119 120 #[derive(Clone, PartialEq, Eq, Debug)] 121 enum FromBytesWithNulErrorKind { 122 InteriorNul(usize), 123 NotNulTerminated, 124 } 125 126 impl FromBytesWithNulError { interior_nul(pos: usize) -> FromBytesWithNulError127 const fn interior_nul(pos: usize) -> FromBytesWithNulError { 128 FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } 129 } not_nul_terminated() -> FromBytesWithNulError130 const fn not_nul_terminated() -> FromBytesWithNulError { 131 FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } 132 } 133 } 134 135 #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] 136 impl Error for FromBytesWithNulError { 137 #[allow(deprecated)] description(&self) -> &str138 fn description(&self) -> &str { 139 match self.kind { 140 FromBytesWithNulErrorKind::InteriorNul(..) => { 141 "data provided contains an interior nul byte" 142 } 143 FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated", 144 } 145 } 146 } 147 148 /// An error indicating that no nul byte was present. 149 /// 150 /// A slice used to create a [`CStr`] must contain a nul byte somewhere 151 /// within the slice. 152 /// 153 /// This error is created by the [`CStr::from_bytes_until_nul`] method. 154 /// 155 #[derive(Clone, PartialEq, Eq, Debug)] 156 #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] 157 pub struct FromBytesUntilNulError(()); 158 159 #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] 160 impl fmt::Display for FromBytesUntilNulError { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 162 write!(f, "data provided does not contain a nul") 163 } 164 } 165 166 #[stable(feature = "cstr_debug", since = "1.3.0")] 167 impl fmt::Debug for CStr { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 169 write!(f, "\"{}\"", self.to_bytes().escape_ascii()) 170 } 171 } 172 173 #[stable(feature = "cstr_default", since = "1.10.0")] 174 impl Default for &CStr { 175 #[inline] default() -> Self176 fn default() -> Self { 177 const SLICE: &[c_char] = &[0]; 178 // SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string. 179 unsafe { CStr::from_ptr(SLICE.as_ptr()) } 180 } 181 } 182 183 #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")] 184 impl fmt::Display for FromBytesWithNulError { 185 #[allow(deprecated, deprecated_in_future)] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 187 f.write_str(self.description())?; 188 if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind { 189 write!(f, " at byte pos {pos}")?; 190 } 191 Ok(()) 192 } 193 } 194 195 impl CStr { 196 /// Wraps a raw C string with a safe C string wrapper. 197 /// 198 /// This function will wrap the provided `ptr` with a `CStr` wrapper, which 199 /// allows inspection and interoperation of non-owned C strings. The total 200 /// size of the raw C string must be smaller than `isize::MAX` **bytes** 201 /// in memory due to calling the `slice::from_raw_parts` function. 202 /// 203 /// # Safety 204 /// 205 /// * The memory pointed to by `ptr` must contain a valid nul terminator at the 206 /// end of the string. 207 /// 208 /// * `ptr` must be [valid] for reads of bytes up to and including the null terminator. 209 /// This means in particular: 210 /// 211 /// * The entire memory range of this `CStr` must be contained within a single allocated object! 212 /// * `ptr` must be non-null even for a zero-length cstr. 213 /// 214 /// * The memory referenced by the returned `CStr` must not be mutated for 215 /// the duration of lifetime `'a`. 216 /// 217 /// > **Note**: This operation is intended to be a 0-cost cast but it is 218 /// > currently implemented with an up-front calculation of the length of 219 /// > the string. This is not guaranteed to always be the case. 220 /// 221 /// # Caveat 222 /// 223 /// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse, 224 /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, 225 /// such as by providing a helper function taking the lifetime of a host value for the slice, 226 /// or by explicit annotation. 227 /// 228 /// # Examples 229 /// 230 /// ```ignore (extern-declaration) 231 /// use std::ffi::{c_char, CStr}; 232 /// 233 /// extern "C" { 234 /// fn my_string() -> *const c_char; 235 /// } 236 /// 237 /// unsafe { 238 /// let slice = CStr::from_ptr(my_string()); 239 /// println!("string returned: {}", slice.to_str().unwrap()); 240 /// } 241 /// ``` 242 /// 243 /// ``` 244 /// #![feature(const_cstr_from_ptr)] 245 /// 246 /// use std::ffi::{c_char, CStr}; 247 /// 248 /// const HELLO_PTR: *const c_char = { 249 /// const BYTES: &[u8] = b"Hello, world!\0"; 250 /// BYTES.as_ptr().cast() 251 /// }; 252 /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; 253 /// ``` 254 /// 255 /// [valid]: core::ptr#safety 256 #[inline] 257 #[must_use] 258 #[stable(feature = "rust1", since = "1.0.0")] 259 #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")] from_ptr<'a>(ptr: *const c_char) -> &'a CStr260 pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { 261 // SAFETY: The caller has provided a pointer that points to a valid C 262 // string with a NUL terminator of size less than `isize::MAX`, whose 263 // content remain valid and doesn't change for the lifetime of the 264 // returned `CStr`. 265 // 266 // Thus computing the length is fine (a NUL byte exists), the call to 267 // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning 268 // the call to `from_bytes_with_nul_unchecked` is correct. 269 // 270 // The cast from c_char to u8 is ok because a c_char is always one byte. 271 unsafe { 272 const fn strlen_ct(s: *const c_char) -> usize { 273 let mut len = 0; 274 275 // SAFETY: Outer caller has provided a pointer to a valid C string. 276 while unsafe { *s.add(len) } != 0 { 277 len += 1; 278 } 279 280 len 281 } 282 283 fn strlen_rt(s: *const c_char) -> usize { 284 extern "C" { 285 /// Provided by libc or compiler_builtins. 286 fn strlen(s: *const c_char) -> usize; 287 } 288 289 // SAFETY: Outer caller has provided a pointer to a valid C string. 290 unsafe { strlen(s) } 291 } 292 293 let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt); 294 Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) 295 } 296 } 297 298 /// Creates a C string wrapper from a byte slice. 299 /// 300 /// This method will create a `CStr` from any byte slice that contains at 301 /// least one nul byte. The caller does not need to know or specify where 302 /// the nul byte is located. 303 /// 304 /// If the first byte is a nul character, this method will return an 305 /// empty `CStr`. If multiple nul characters are present, the `CStr` will 306 /// end at the first one. 307 /// 308 /// If the slice only has a single nul byte at the end, this method is 309 /// equivalent to [`CStr::from_bytes_with_nul`]. 310 /// 311 /// # Examples 312 /// ``` 313 /// use std::ffi::CStr; 314 /// 315 /// let mut buffer = [0u8; 16]; 316 /// unsafe { 317 /// // Here we might call an unsafe C function that writes a string 318 /// // into the buffer. 319 /// let buf_ptr = buffer.as_mut_ptr(); 320 /// buf_ptr.write_bytes(b'A', 8); 321 /// } 322 /// // Attempt to extract a C nul-terminated string from the buffer. 323 /// let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap(); 324 /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA"); 325 /// ``` 326 /// 327 #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] 328 #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError>329 pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { 330 let nul_pos = memchr::memchr(0, bytes); 331 match nul_pos { 332 Some(nul_pos) => { 333 // FIXME(const-hack) replace with range index 334 // SAFETY: nul_pos + 1 <= bytes.len() 335 let subslice = unsafe { crate::slice::from_raw_parts(bytes.as_ptr(), nul_pos + 1) }; 336 // SAFETY: We know there is a nul byte at nul_pos, so this slice 337 // (ending at the nul byte) is a well-formed C string. 338 Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) }) 339 } 340 None => Err(FromBytesUntilNulError(())), 341 } 342 } 343 344 /// Creates a C string wrapper from a byte slice. 345 /// 346 /// This function will cast the provided `bytes` to a `CStr` 347 /// wrapper after ensuring that the byte slice is nul-terminated 348 /// and does not contain any interior nul bytes. 349 /// 350 /// If the nul byte may not be at the end, 351 /// [`CStr::from_bytes_until_nul`] can be used instead. 352 /// 353 /// # Examples 354 /// 355 /// ``` 356 /// use std::ffi::CStr; 357 /// 358 /// let cstr = CStr::from_bytes_with_nul(b"hello\0"); 359 /// assert!(cstr.is_ok()); 360 /// ``` 361 /// 362 /// Creating a `CStr` without a trailing nul terminator is an error: 363 /// 364 /// ``` 365 /// use std::ffi::CStr; 366 /// 367 /// let cstr = CStr::from_bytes_with_nul(b"hello"); 368 /// assert!(cstr.is_err()); 369 /// ``` 370 /// 371 /// Creating a `CStr` with an interior nul byte is an error: 372 /// 373 /// ``` 374 /// use std::ffi::CStr; 375 /// 376 /// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0"); 377 /// assert!(cstr.is_err()); 378 /// ``` 379 #[stable(feature = "cstr_from_bytes", since = "1.10.0")] 380 #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>381 pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { 382 let nul_pos = memchr::memchr(0, bytes); 383 match nul_pos { 384 Some(nul_pos) if nul_pos + 1 == bytes.len() => { 385 // SAFETY: We know there is only one nul byte, at the end 386 // of the byte slice. 387 Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) 388 } 389 Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), 390 None => Err(FromBytesWithNulError::not_nul_terminated()), 391 } 392 } 393 394 /// Unsafely creates a C string wrapper from a byte slice. 395 /// 396 /// This function will cast the provided `bytes` to a `CStr` wrapper without 397 /// performing any sanity checks. 398 /// 399 /// # Safety 400 /// The provided slice **must** be nul-terminated and not contain any interior 401 /// nul bytes. 402 /// 403 /// # Examples 404 /// 405 /// ``` 406 /// use std::ffi::{CStr, CString}; 407 /// 408 /// unsafe { 409 /// let cstring = CString::new("hello").expect("CString::new failed"); 410 /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()); 411 /// assert_eq!(cstr, &*cstring); 412 /// } 413 /// ``` 414 #[inline] 415 #[must_use] 416 #[stable(feature = "cstr_from_bytes", since = "1.10.0")] 417 #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] 418 #[rustc_allow_const_fn_unstable(const_eval_select)] from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr419 pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { 420 #[inline] 421 fn rt_impl(bytes: &[u8]) -> &CStr { 422 // Chance at catching some UB at runtime with debug builds. 423 debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); 424 425 // SAFETY: Casting to CStr is safe because its internal representation 426 // is a [u8] too (safe only inside std). 427 // Dereferencing the obtained pointer is safe because it comes from a 428 // reference. Making a reference is then safe because its lifetime 429 // is bound by the lifetime of the given `bytes`. 430 unsafe { &*(bytes as *const [u8] as *const CStr) } 431 } 432 433 const fn const_impl(bytes: &[u8]) -> &CStr { 434 // Saturating so that an empty slice panics in the assert with a good 435 // message, not here due to underflow. 436 let mut i = bytes.len().saturating_sub(1); 437 assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated"); 438 439 // Ending null byte exists, skip to the rest. 440 while i != 0 { 441 i -= 1; 442 let byte = bytes[i]; 443 assert!(byte != 0, "input contained interior nul"); 444 } 445 446 // SAFETY: See `rt_impl` cast. 447 unsafe { &*(bytes as *const [u8] as *const CStr) } 448 } 449 450 // SAFETY: The const and runtime versions have identical behavior 451 // unless the safety contract of `from_bytes_with_nul_unchecked` is 452 // violated, which is UB. 453 unsafe { intrinsics::const_eval_select((bytes,), const_impl, rt_impl) } 454 } 455 456 /// Returns the inner pointer to this C string. 457 /// 458 /// The returned pointer will be valid for as long as `self` is, and points 459 /// to a contiguous region of memory terminated with a 0 byte to represent 460 /// the end of the string. 461 /// 462 /// The type of the returned pointer is 463 /// [`*const c_char`][crate::ffi::c_char], and whether it's 464 /// an alias for `*const i8` or `*const u8` is platform-specific. 465 /// 466 /// **WARNING** 467 /// 468 /// The returned pointer is read-only; writing to it (including passing it 469 /// to C code that writes to it) causes undefined behavior. 470 /// 471 /// It is your responsibility to make sure that the underlying memory is not 472 /// freed too early. For example, the following code will cause undefined 473 /// behavior when `ptr` is used inside the `unsafe` block: 474 /// 475 /// ```no_run 476 /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)] 477 /// use std::ffi::CString; 478 /// 479 /// // Do not do this: 480 /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr(); 481 /// unsafe { 482 /// // `ptr` is dangling 483 /// *ptr; 484 /// } 485 /// ``` 486 /// 487 /// This happens because the pointer returned by `as_ptr` does not carry any 488 /// lifetime information and the `CString` is deallocated immediately after 489 /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` 490 /// expression is evaluated. 491 /// To fix the problem, bind the `CString` to a local variable: 492 /// 493 /// ```no_run 494 /// # #![allow(unused_must_use)] 495 /// use std::ffi::CString; 496 /// 497 /// let hello = CString::new("Hello").expect("CString::new failed"); 498 /// let ptr = hello.as_ptr(); 499 /// unsafe { 500 /// // `ptr` is valid because `hello` is in scope 501 /// *ptr; 502 /// } 503 /// ``` 504 /// 505 /// This way, the lifetime of the `CString` in `hello` encompasses 506 /// the lifetime of `ptr` and the `unsafe` block. 507 #[inline] 508 #[must_use] 509 #[stable(feature = "rust1", since = "1.0.0")] 510 #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] as_ptr(&self) -> *const c_char511 pub const fn as_ptr(&self) -> *const c_char { 512 self.inner.as_ptr() 513 } 514 515 /// Returns `true` if `self.to_bytes()` has a length of 0. 516 /// 517 /// # Examples 518 /// 519 /// ``` 520 /// use std::ffi::CStr; 521 /// # use std::ffi::FromBytesWithNulError; 522 /// 523 /// # fn main() { test().unwrap(); } 524 /// # fn test() -> Result<(), FromBytesWithNulError> { 525 /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?; 526 /// assert!(!cstr.is_empty()); 527 /// 528 /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?; 529 /// assert!(empty_cstr.is_empty()); 530 /// # Ok(()) 531 /// # } 532 /// ``` 533 #[inline] 534 #[stable(feature = "cstr_is_empty", since = "1.71.0")] 535 #[rustc_const_stable(feature = "cstr_is_empty", since = "1.71.0")] is_empty(&self) -> bool536 pub const fn is_empty(&self) -> bool { 537 // SAFETY: We know there is at least one byte; for empty strings it 538 // is the NUL terminator. 539 // FIXME(const-hack): use get_unchecked 540 unsafe { *self.inner.as_ptr() == 0 } 541 } 542 543 /// Converts this C string to a byte slice. 544 /// 545 /// The returned slice will **not** contain the trailing nul terminator that this C 546 /// string has. 547 /// 548 /// > **Note**: This method is currently implemented as a constant-time 549 /// > cast, but it is planned to alter its definition in the future to 550 /// > perform the length calculation whenever this method is called. 551 /// 552 /// # Examples 553 /// 554 /// ``` 555 /// use std::ffi::CStr; 556 /// 557 /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); 558 /// assert_eq!(cstr.to_bytes(), b"foo"); 559 /// ``` 560 #[inline] 561 #[must_use = "this returns the result of the operation, \ 562 without modifying the original"] 563 #[stable(feature = "rust1", since = "1.0.0")] 564 #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] to_bytes(&self) -> &[u8]565 pub const fn to_bytes(&self) -> &[u8] { 566 let bytes = self.to_bytes_with_nul(); 567 // FIXME(const-hack) replace with range index 568 // SAFETY: to_bytes_with_nul returns slice with length at least 1 569 unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) } 570 } 571 572 /// Converts this C string to a byte slice containing the trailing 0 byte. 573 /// 574 /// This function is the equivalent of [`CStr::to_bytes`] except that it 575 /// will retain the trailing nul terminator instead of chopping it off. 576 /// 577 /// > **Note**: This method is currently implemented as a 0-cost cast, but 578 /// > it is planned to alter its definition in the future to perform the 579 /// > length calculation whenever this method is called. 580 /// 581 /// # Examples 582 /// 583 /// ``` 584 /// use std::ffi::CStr; 585 /// 586 /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); 587 /// assert_eq!(cstr.to_bytes_with_nul(), b"foo\0"); 588 /// ``` 589 #[inline] 590 #[must_use = "this returns the result of the operation, \ 591 without modifying the original"] 592 #[stable(feature = "rust1", since = "1.0.0")] 593 #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] to_bytes_with_nul(&self) -> &[u8]594 pub const fn to_bytes_with_nul(&self) -> &[u8] { 595 // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s 596 // is safe on all supported targets. 597 unsafe { &*(&self.inner as *const [c_char] as *const [u8]) } 598 } 599 600 /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8. 601 /// 602 /// If the contents of the `CStr` are valid UTF-8 data, this 603 /// function will return the corresponding <code>&[str]</code> slice. Otherwise, 604 /// it will return an error with details of where UTF-8 validation failed. 605 /// 606 /// [str]: prim@str "str" 607 /// 608 /// # Examples 609 /// 610 /// ``` 611 /// use std::ffi::CStr; 612 /// 613 /// let cstr = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"); 614 /// assert_eq!(cstr.to_str(), Ok("foo")); 615 /// ``` 616 #[stable(feature = "cstr_to_str", since = "1.4.0")] 617 #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")] to_str(&self) -> Result<&str, str::Utf8Error>618 pub const fn to_str(&self) -> Result<&str, str::Utf8Error> { 619 // N.B., when `CStr` is changed to perform the length check in `.to_bytes()` 620 // instead of in `from_ptr()`, it may be worth considering if this should 621 // be rewritten to do the UTF-8 check inline with the length calculation 622 // instead of doing it afterwards. 623 str::from_utf8(self.to_bytes()) 624 } 625 } 626 627 #[stable(feature = "rust1", since = "1.0.0")] 628 impl PartialEq for CStr { 629 #[inline] eq(&self, other: &CStr) -> bool630 fn eq(&self, other: &CStr) -> bool { 631 self.to_bytes().eq(other.to_bytes()) 632 } 633 } 634 #[stable(feature = "rust1", since = "1.0.0")] 635 impl Eq for CStr {} 636 #[stable(feature = "rust1", since = "1.0.0")] 637 impl PartialOrd for CStr { 638 #[inline] partial_cmp(&self, other: &CStr) -> Option<Ordering>639 fn partial_cmp(&self, other: &CStr) -> Option<Ordering> { 640 self.to_bytes().partial_cmp(&other.to_bytes()) 641 } 642 } 643 #[stable(feature = "rust1", since = "1.0.0")] 644 impl Ord for CStr { 645 #[inline] cmp(&self, other: &CStr) -> Ordering646 fn cmp(&self, other: &CStr) -> Ordering { 647 self.to_bytes().cmp(&other.to_bytes()) 648 } 649 } 650 651 #[stable(feature = "cstr_range_from", since = "1.47.0")] 652 impl ops::Index<ops::RangeFrom<usize>> for CStr { 653 type Output = CStr; 654 655 #[inline] index(&self, index: ops::RangeFrom<usize>) -> &CStr656 fn index(&self, index: ops::RangeFrom<usize>) -> &CStr { 657 let bytes = self.to_bytes_with_nul(); 658 // we need to manually check the starting index to account for the null 659 // byte, since otherwise we could get an empty string that doesn't end 660 // in a null. 661 if index.start < bytes.len() { 662 // SAFETY: Non-empty tail of a valid `CStr` is still a valid `CStr`. 663 unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } 664 } else { 665 panic!( 666 "index out of bounds: the len is {} but the index is {}", 667 bytes.len(), 668 index.start 669 ); 670 } 671 } 672 } 673 674 #[stable(feature = "cstring_asref", since = "1.7.0")] 675 impl AsRef<CStr> for CStr { 676 #[inline] as_ref(&self) -> &CStr677 fn as_ref(&self) -> &CStr { 678 self 679 } 680 } 681