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 does **not** have a guaranteed layout (the `repr(transparent)` |
24 | /// notwithstanding) and is not recommended to be placed in the signatures of FFI functions. |
25 | /// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor |
26 | /// to provide 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 | // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies |
86 | // on `CStr` being layout-compatible with `[u8]`. |
87 | // However, `CStr` layout is considered an implementation detail and must not be relied upon. We |
88 | // want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under |
89 | // `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. |
90 | #[cfg_attr (not(doc), repr(transparent))] |
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 { |
127 | const fn interior_nul(pos: usize) -> FromBytesWithNulError { |
128 | FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } |
129 | } |
130 | 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)] |
138 | 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 { |
161 | 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 { |
168 | 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 ] |
176 | 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)] |
186 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
187 | f.write_str(self.description())?; |
188 | if let FromBytesWithNulErrorKind::InteriorNul(pos: usize) = 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 terminated buffer must be smaller than [`isize::MAX`] **bytes** |
201 | /// in memory (a restriction from [`slice::from_raw_parts`]). |
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 nul 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 | /// * The nul terminator must be within `isize::MAX` from `ptr` |
218 | /// |
219 | /// > **Note**: This operation is intended to be a 0-cost cast but it is |
220 | /// > currently implemented with an up-front calculation of the length of |
221 | /// > the string. This is not guaranteed to always be the case. |
222 | /// |
223 | /// # Caveat |
224 | /// |
225 | /// The lifetime for the returned slice is inferred from its usage. To prevent accidental misuse, |
226 | /// it's suggested to tie the lifetime to whichever source lifetime is safe in the context, |
227 | /// such as by providing a helper function taking the lifetime of a host value for the slice, |
228 | /// or by explicit annotation. |
229 | /// |
230 | /// # Examples |
231 | /// |
232 | /// ```ignore (extern-declaration) |
233 | /// use std::ffi::{c_char, CStr}; |
234 | /// |
235 | /// extern "C" { |
236 | /// fn my_string() -> *const c_char; |
237 | /// } |
238 | /// |
239 | /// unsafe { |
240 | /// let slice = CStr::from_ptr(my_string()); |
241 | /// println!("string returned: {}" , slice.to_str().unwrap()); |
242 | /// } |
243 | /// ``` |
244 | /// |
245 | /// ``` |
246 | /// #![feature(const_cstr_from_ptr)] |
247 | /// |
248 | /// use std::ffi::{c_char, CStr}; |
249 | /// |
250 | /// const HELLO_PTR: *const c_char = { |
251 | /// const BYTES: &[u8] = b"Hello, world! \0" ; |
252 | /// BYTES.as_ptr().cast() |
253 | /// }; |
254 | /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; |
255 | /// ``` |
256 | /// |
257 | /// [valid]: core::ptr#safety |
258 | #[inline ] // inline is necessary for codegen to see strlen. |
259 | #[must_use ] |
260 | #[stable (feature = "rust1" , since = "1.0.0" )] |
261 | #[rustc_const_unstable (feature = "const_cstr_from_ptr" , issue = "113219" )] |
262 | pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { |
263 | // SAFETY: The caller has provided a pointer that points to a valid C |
264 | // string with a NUL terminator less than `isize::MAX` from `ptr`. |
265 | let len = unsafe { const_strlen(ptr) }; |
266 | |
267 | // SAFETY: The caller has provided a valid pointer with length less than |
268 | // `isize::MAX`, so `from_raw_parts` is safe. The content remains valid |
269 | // and doesn't change for the lifetime of the returned `CStr`. This |
270 | // means the call to `from_bytes_with_nul_unchecked` is correct. |
271 | // |
272 | // The cast from c_char to u8 is ok because a c_char is always one byte. |
273 | unsafe { Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) } |
274 | } |
275 | |
276 | /// Creates a C string wrapper from a byte slice with any number of nuls. |
277 | /// |
278 | /// This method will create a `CStr` from any byte slice that contains at |
279 | /// least one nul byte. Unlike with [`CStr::from_bytes_with_nul`], the caller |
280 | /// does not need to know where the nul byte is located. |
281 | /// |
282 | /// If the first byte is a nul character, this method will return an |
283 | /// empty `CStr`. If multiple nul characters are present, the `CStr` will |
284 | /// end at the first one. |
285 | /// |
286 | /// If the slice only has a single nul byte at the end, this method is |
287 | /// equivalent to [`CStr::from_bytes_with_nul`]. |
288 | /// |
289 | /// # Examples |
290 | /// ``` |
291 | /// use std::ffi::CStr; |
292 | /// |
293 | /// let mut buffer = [0u8; 16]; |
294 | /// unsafe { |
295 | /// // Here we might call an unsafe C function that writes a string |
296 | /// // into the buffer. |
297 | /// let buf_ptr = buffer.as_mut_ptr(); |
298 | /// buf_ptr.write_bytes(b'A' , 8); |
299 | /// } |
300 | /// // Attempt to extract a C nul-terminated string from the buffer. |
301 | /// let c_str = CStr::from_bytes_until_nul(&buffer[..]).unwrap(); |
302 | /// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA" ); |
303 | /// ``` |
304 | /// |
305 | #[stable (feature = "cstr_from_bytes_until_nul" , since = "1.69.0" )] |
306 | #[rustc_const_stable (feature = "cstr_from_bytes_until_nul" , since = "1.69.0" )] |
307 | pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { |
308 | let nul_pos = memchr::memchr(0, bytes); |
309 | match nul_pos { |
310 | Some(nul_pos) => { |
311 | // FIXME(const-hack) replace with range index |
312 | // SAFETY: nul_pos + 1 <= bytes.len() |
313 | let subslice = unsafe { crate::slice::from_raw_parts(bytes.as_ptr(), nul_pos + 1) }; |
314 | // SAFETY: We know there is a nul byte at nul_pos, so this slice |
315 | // (ending at the nul byte) is a well-formed C string. |
316 | Ok(unsafe { CStr::from_bytes_with_nul_unchecked(subslice) }) |
317 | } |
318 | None => Err(FromBytesUntilNulError(())), |
319 | } |
320 | } |
321 | |
322 | /// Creates a C string wrapper from a byte slice with exactly one nul |
323 | /// terminator. |
324 | /// |
325 | /// This function will cast the provided `bytes` to a `CStr` |
326 | /// wrapper after ensuring that the byte slice is nul-terminated |
327 | /// and does not contain any interior nul bytes. |
328 | /// |
329 | /// If the nul byte may not be at the end, |
330 | /// [`CStr::from_bytes_until_nul`] can be used instead. |
331 | /// |
332 | /// # Examples |
333 | /// |
334 | /// ``` |
335 | /// use std::ffi::CStr; |
336 | /// |
337 | /// let cstr = CStr::from_bytes_with_nul(b"hello \0" ); |
338 | /// assert!(cstr.is_ok()); |
339 | /// ``` |
340 | /// |
341 | /// Creating a `CStr` without a trailing nul terminator is an error: |
342 | /// |
343 | /// ``` |
344 | /// use std::ffi::CStr; |
345 | /// |
346 | /// let cstr = CStr::from_bytes_with_nul(b"hello" ); |
347 | /// assert!(cstr.is_err()); |
348 | /// ``` |
349 | /// |
350 | /// Creating a `CStr` with an interior nul byte is an error: |
351 | /// |
352 | /// ``` |
353 | /// use std::ffi::CStr; |
354 | /// |
355 | /// let cstr = CStr::from_bytes_with_nul(b"he \0llo \0" ); |
356 | /// assert!(cstr.is_err()); |
357 | /// ``` |
358 | #[stable (feature = "cstr_from_bytes" , since = "1.10.0" )] |
359 | #[rustc_const_stable (feature = "const_cstr_methods" , since = "1.72.0" )] |
360 | pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { |
361 | let nul_pos = memchr::memchr(0, bytes); |
362 | match nul_pos { |
363 | Some(nul_pos) if nul_pos + 1 == bytes.len() => { |
364 | // SAFETY: We know there is only one nul byte, at the end |
365 | // of the byte slice. |
366 | Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) |
367 | } |
368 | Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), |
369 | None => Err(FromBytesWithNulError::not_nul_terminated()), |
370 | } |
371 | } |
372 | |
373 | /// Unsafely creates a C string wrapper from a byte slice. |
374 | /// |
375 | /// This function will cast the provided `bytes` to a `CStr` wrapper without |
376 | /// performing any sanity checks. |
377 | /// |
378 | /// # Safety |
379 | /// The provided slice **must** be nul-terminated and not contain any interior |
380 | /// nul bytes. |
381 | /// |
382 | /// # Examples |
383 | /// |
384 | /// ``` |
385 | /// use std::ffi::{CStr, CString}; |
386 | /// |
387 | /// unsafe { |
388 | /// let cstring = CString::new("hello" ).expect("CString::new failed" ); |
389 | /// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul()); |
390 | /// assert_eq!(cstr, &*cstring); |
391 | /// } |
392 | /// ``` |
393 | #[inline ] |
394 | #[must_use ] |
395 | #[stable (feature = "cstr_from_bytes" , since = "1.10.0" )] |
396 | #[rustc_const_stable (feature = "const_cstr_unchecked" , since = "1.59.0" )] |
397 | #[rustc_allow_const_fn_unstable (const_eval_select)] |
398 | pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { |
399 | #[inline ] |
400 | fn rt_impl(bytes: &[u8]) -> &CStr { |
401 | // Chance at catching some UB at runtime with debug builds. |
402 | debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); |
403 | |
404 | // SAFETY: Casting to CStr is safe because its internal representation |
405 | // is a [u8] too (safe only inside std). |
406 | // Dereferencing the obtained pointer is safe because it comes from a |
407 | // reference. Making a reference is then safe because its lifetime |
408 | // is bound by the lifetime of the given `bytes`. |
409 | unsafe { &*(bytes as *const [u8] as *const CStr) } |
410 | } |
411 | |
412 | const fn const_impl(bytes: &[u8]) -> &CStr { |
413 | // Saturating so that an empty slice panics in the assert with a good |
414 | // message, not here due to underflow. |
415 | let mut i = bytes.len().saturating_sub(1); |
416 | assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated" ); |
417 | |
418 | // Ending nul byte exists, skip to the rest. |
419 | while i != 0 { |
420 | i -= 1; |
421 | let byte = bytes[i]; |
422 | assert!(byte != 0, "input contained interior nul" ); |
423 | } |
424 | |
425 | // SAFETY: See `rt_impl` cast. |
426 | unsafe { &*(bytes as *const [u8] as *const CStr) } |
427 | } |
428 | |
429 | // SAFETY: The const and runtime versions have identical behavior |
430 | // unless the safety contract of `from_bytes_with_nul_unchecked` is |
431 | // violated, which is UB. |
432 | unsafe { intrinsics::const_eval_select((bytes,), const_impl, rt_impl) } |
433 | } |
434 | |
435 | /// Returns the inner pointer to this C string. |
436 | /// |
437 | /// The returned pointer will be valid for as long as `self` is, and points |
438 | /// to a contiguous region of memory terminated with a 0 byte to represent |
439 | /// the end of the string. |
440 | /// |
441 | /// The type of the returned pointer is |
442 | /// [`*const c_char`][crate::ffi::c_char], and whether it's |
443 | /// an alias for `*const i8` or `*const u8` is platform-specific. |
444 | /// |
445 | /// **WARNING** |
446 | /// |
447 | /// The returned pointer is read-only; writing to it (including passing it |
448 | /// to C code that writes to it) causes undefined behavior. |
449 | /// |
450 | /// It is your responsibility to make sure that the underlying memory is not |
451 | /// freed too early. For example, the following code will cause undefined |
452 | /// behavior when `ptr` is used inside the `unsafe` block: |
453 | /// |
454 | /// ```no_run |
455 | /// # #![allow (unused_must_use)] #![allow (temporary_cstring_as_ptr)] |
456 | /// use std::ffi::CString; |
457 | /// |
458 | /// // Do not do this: |
459 | /// let ptr = CString::new("Hello" ).expect("CString::new failed" ).as_ptr(); |
460 | /// unsafe { |
461 | /// // `ptr` is dangling |
462 | /// *ptr; |
463 | /// } |
464 | /// ``` |
465 | /// |
466 | /// This happens because the pointer returned by `as_ptr` does not carry any |
467 | /// lifetime information and the `CString` is deallocated immediately after |
468 | /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` |
469 | /// expression is evaluated. |
470 | /// To fix the problem, bind the `CString` to a local variable: |
471 | /// |
472 | /// ```no_run |
473 | /// # #![allow(unused_must_use)] |
474 | /// use std::ffi::CString; |
475 | /// |
476 | /// let hello = CString::new("Hello" ).expect("CString::new failed" ); |
477 | /// let ptr = hello.as_ptr(); |
478 | /// unsafe { |
479 | /// // `ptr` is valid because `hello` is in scope |
480 | /// *ptr; |
481 | /// } |
482 | /// ``` |
483 | /// |
484 | /// This way, the lifetime of the `CString` in `hello` encompasses |
485 | /// the lifetime of `ptr` and the `unsafe` block. |
486 | #[inline ] |
487 | #[must_use ] |
488 | #[stable (feature = "rust1" , since = "1.0.0" )] |
489 | #[rustc_const_stable (feature = "const_str_as_ptr" , since = "1.32.0" )] |
490 | #[rustc_never_returns_null_ptr ] |
491 | pub const fn as_ptr(&self) -> *const c_char { |
492 | self.inner.as_ptr() |
493 | } |
494 | |
495 | /// Returns the length of `self`. Like C's `strlen`, this does not include the nul terminator. |
496 | /// |
497 | /// > **Note**: This method is currently implemented as a constant-time |
498 | /// > cast, but it is planned to alter its definition in the future to |
499 | /// > perform the length calculation whenever this method is called. |
500 | /// |
501 | /// # Examples |
502 | /// |
503 | /// ``` |
504 | /// #![feature(cstr_count_bytes)] |
505 | /// |
506 | /// use std::ffi::CStr; |
507 | /// |
508 | /// let cstr = CStr::from_bytes_with_nul(b"foo \0" ).unwrap(); |
509 | /// assert_eq!(cstr.count_bytes(), 3); |
510 | /// |
511 | /// let cstr = CStr::from_bytes_with_nul(b" \0" ).unwrap(); |
512 | /// assert_eq!(cstr.count_bytes(), 0); |
513 | /// ``` |
514 | #[inline ] |
515 | #[must_use ] |
516 | #[doc (alias("len" , "strlen" ))] |
517 | #[unstable (feature = "cstr_count_bytes" , issue = "114441" )] |
518 | #[rustc_const_unstable (feature = "const_cstr_from_ptr" , issue = "113219" )] |
519 | pub const fn count_bytes(&self) -> usize { |
520 | self.inner.len() - 1 |
521 | } |
522 | |
523 | /// Returns `true` if `self.to_bytes()` has a length of 0. |
524 | /// |
525 | /// # Examples |
526 | /// |
527 | /// ``` |
528 | /// use std::ffi::CStr; |
529 | /// # use std::ffi::FromBytesWithNulError; |
530 | /// |
531 | /// # fn main() { test().unwrap(); } |
532 | /// # fn test() -> Result<(), FromBytesWithNulError> { |
533 | /// let cstr = CStr::from_bytes_with_nul(b"foo \0" )?; |
534 | /// assert!(!cstr.is_empty()); |
535 | /// |
536 | /// let empty_cstr = CStr::from_bytes_with_nul(b" \0" )?; |
537 | /// assert!(empty_cstr.is_empty()); |
538 | /// # Ok(()) |
539 | /// # } |
540 | /// ``` |
541 | #[inline ] |
542 | #[stable (feature = "cstr_is_empty" , since = "1.71.0" )] |
543 | #[rustc_const_stable (feature = "cstr_is_empty" , since = "1.71.0" )] |
544 | pub const fn is_empty(&self) -> bool { |
545 | // SAFETY: We know there is at least one byte; for empty strings it |
546 | // is the NUL terminator. |
547 | // FIXME(const-hack): use get_unchecked |
548 | unsafe { *self.inner.as_ptr() == 0 } |
549 | } |
550 | |
551 | /// Converts this C string to a byte slice. |
552 | /// |
553 | /// The returned slice will **not** contain the trailing nul terminator that this C |
554 | /// string has. |
555 | /// |
556 | /// > **Note**: This method is currently implemented as a constant-time |
557 | /// > cast, but it is planned to alter its definition in the future to |
558 | /// > perform the length calculation whenever this method is called. |
559 | /// |
560 | /// # Examples |
561 | /// |
562 | /// ``` |
563 | /// use std::ffi::CStr; |
564 | /// |
565 | /// let cstr = CStr::from_bytes_with_nul(b"foo \0" ).expect("CStr::from_bytes_with_nul failed" ); |
566 | /// assert_eq!(cstr.to_bytes(), b"foo" ); |
567 | /// ``` |
568 | #[inline ] |
569 | #[must_use = "this returns the result of the operation, \ |
570 | without modifying the original" ] |
571 | #[stable (feature = "rust1" , since = "1.0.0" )] |
572 | #[rustc_const_stable (feature = "const_cstr_methods" , since = "1.72.0" )] |
573 | pub const fn to_bytes(&self) -> &[u8] { |
574 | let bytes = self.to_bytes_with_nul(); |
575 | // FIXME(const-hack) replace with range index |
576 | // SAFETY: to_bytes_with_nul returns slice with length at least 1 |
577 | unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) } |
578 | } |
579 | |
580 | /// Converts this C string to a byte slice containing the trailing 0 byte. |
581 | /// |
582 | /// This function is the equivalent of [`CStr::to_bytes`] except that it |
583 | /// will retain the trailing nul terminator instead of chopping it off. |
584 | /// |
585 | /// > **Note**: This method is currently implemented as a 0-cost cast, but |
586 | /// > it is planned to alter its definition in the future to perform the |
587 | /// > length calculation whenever this method is called. |
588 | /// |
589 | /// # Examples |
590 | /// |
591 | /// ``` |
592 | /// use std::ffi::CStr; |
593 | /// |
594 | /// let cstr = CStr::from_bytes_with_nul(b"foo \0" ).expect("CStr::from_bytes_with_nul failed" ); |
595 | /// assert_eq!(cstr.to_bytes_with_nul(), b"foo \0" ); |
596 | /// ``` |
597 | #[inline ] |
598 | #[must_use = "this returns the result of the operation, \ |
599 | without modifying the original" ] |
600 | #[stable (feature = "rust1" , since = "1.0.0" )] |
601 | #[rustc_const_stable (feature = "const_cstr_methods" , since = "1.72.0" )] |
602 | pub const fn to_bytes_with_nul(&self) -> &[u8] { |
603 | // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s |
604 | // is safe on all supported targets. |
605 | unsafe { &*(&self.inner as *const [c_char] as *const [u8]) } |
606 | } |
607 | |
608 | /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8. |
609 | /// |
610 | /// If the contents of the `CStr` are valid UTF-8 data, this |
611 | /// function will return the corresponding <code>&[str]</code> slice. Otherwise, |
612 | /// it will return an error with details of where UTF-8 validation failed. |
613 | /// |
614 | /// [str]: prim@str "str" |
615 | /// |
616 | /// # Examples |
617 | /// |
618 | /// ``` |
619 | /// use std::ffi::CStr; |
620 | /// |
621 | /// let cstr = CStr::from_bytes_with_nul(b"foo \0" ).expect("CStr::from_bytes_with_nul failed" ); |
622 | /// assert_eq!(cstr.to_str(), Ok("foo" )); |
623 | /// ``` |
624 | #[stable (feature = "cstr_to_str" , since = "1.4.0" )] |
625 | #[rustc_const_stable (feature = "const_cstr_methods" , since = "1.72.0" )] |
626 | pub const fn to_str(&self) -> Result<&str, str::Utf8Error> { |
627 | // N.B., when `CStr` is changed to perform the length check in `.to_bytes()` |
628 | // instead of in `from_ptr()`, it may be worth considering if this should |
629 | // be rewritten to do the UTF-8 check inline with the length calculation |
630 | // instead of doing it afterwards. |
631 | str::from_utf8(self.to_bytes()) |
632 | } |
633 | } |
634 | |
635 | #[stable (feature = "rust1" , since = "1.0.0" )] |
636 | impl PartialEq for CStr { |
637 | #[inline ] |
638 | fn eq(&self, other: &CStr) -> bool { |
639 | self.to_bytes().eq(other.to_bytes()) |
640 | } |
641 | } |
642 | #[stable (feature = "rust1" , since = "1.0.0" )] |
643 | impl Eq for CStr {} |
644 | #[stable (feature = "rust1" , since = "1.0.0" )] |
645 | impl PartialOrd for CStr { |
646 | #[inline ] |
647 | fn partial_cmp(&self, other: &CStr) -> Option<Ordering> { |
648 | self.to_bytes().partial_cmp(&other.to_bytes()) |
649 | } |
650 | } |
651 | #[stable (feature = "rust1" , since = "1.0.0" )] |
652 | impl Ord for CStr { |
653 | #[inline ] |
654 | fn cmp(&self, other: &CStr) -> Ordering { |
655 | self.to_bytes().cmp(&other.to_bytes()) |
656 | } |
657 | } |
658 | |
659 | #[stable (feature = "cstr_range_from" , since = "1.47.0" )] |
660 | impl ops::Index<ops::RangeFrom<usize>> for CStr { |
661 | type Output = CStr; |
662 | |
663 | #[inline ] |
664 | fn index(&self, index: ops::RangeFrom<usize>) -> &CStr { |
665 | let bytes: &[u8] = self.to_bytes_with_nul(); |
666 | // we need to manually check the starting index to account for the null |
667 | // byte, since otherwise we could get an empty string that doesn't end |
668 | // in a null. |
669 | if index.start < bytes.len() { |
670 | // SAFETY: Non-empty tail of a valid `CStr` is still a valid `CStr`. |
671 | unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } |
672 | } else { |
673 | panic!( |
674 | "index out of bounds: the len is {} but the index is {}" , |
675 | bytes.len(), |
676 | index.start |
677 | ); |
678 | } |
679 | } |
680 | } |
681 | |
682 | #[stable (feature = "cstring_asref" , since = "1.7.0" )] |
683 | impl AsRef<CStr> for CStr { |
684 | #[inline ] |
685 | fn as_ref(&self) -> &CStr { |
686 | self |
687 | } |
688 | } |
689 | |
690 | /// Calculate the length of a nul-terminated string. Defers to C's `strlen` when possible. |
691 | /// |
692 | /// # Safety |
693 | /// |
694 | /// The pointer must point to a valid buffer that contains a NUL terminator. The NUL must be |
695 | /// located within `isize::MAX` from `ptr`. |
696 | #[inline ] |
697 | const unsafe fn const_strlen(ptr: *const c_char) -> usize { |
698 | const fn strlen_ct(s: *const c_char) -> usize { |
699 | let mut len = 0; |
700 | |
701 | // SAFETY: Outer caller has provided a pointer to a valid C string. |
702 | while unsafe { *s.add(len) } != 0 { |
703 | len += 1; |
704 | } |
705 | |
706 | len |
707 | } |
708 | |
709 | #[inline ] |
710 | fn strlen_rt(s: *const c_char) -> usize { |
711 | extern "C" { |
712 | /// Provided by libc or compiler_builtins. |
713 | fn strlen(s: *const c_char) -> usize; |
714 | } |
715 | |
716 | // SAFETY: Outer caller has provided a pointer to a valid C string. |
717 | unsafe { strlen(s) } |
718 | } |
719 | |
720 | // SAFETY: the two functions always provide equivalent functionality |
721 | unsafe { intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt) } |
722 | } |
723 | |