|
5 | 5 | use crate::alloc::{flags::*, vec_ext::VecExt, AllocError};
|
6 | 6 | use alloc::vec::Vec;
|
7 | 7 | use core::fmt::{self, Write};
|
8 |
| -use core::ops::{self, Deref, Index}; |
| 8 | +use core::ops::{self, Deref, DerefMut, Index}; |
9 | 9 |
|
10 | 10 | use crate::{
|
11 | 11 | bindings,
|
@@ -236,6 +236,19 @@ impl CStr {
|
236 | 236 | unsafe { core::mem::transmute(bytes) }
|
237 | 237 | }
|
238 | 238 |
|
| 239 | + /// Creates a mutable [`CStr`] from a `[u8]` without performing any |
| 240 | + /// additional checks. |
| 241 | + /// |
| 242 | + /// # Safety |
| 243 | + /// |
| 244 | + /// `bytes` *must* end with a `NUL` byte, and should only have a single |
| 245 | + /// `NUL` byte (or the string will be truncated). |
| 246 | + #[inline] |
| 247 | + pub unsafe fn from_bytes_with_nul_unchecked_mut(bytes: &mut [u8]) -> &mut CStr { |
| 248 | + // SAFETY: Properties of `bytes` guaranteed by the safety precondition. |
| 249 | + unsafe { &mut *(bytes as *mut [u8] as *mut CStr) } |
| 250 | + } |
| 251 | + |
239 | 252 | /// Returns a C pointer to the string.
|
240 | 253 | #[inline]
|
241 | 254 | pub const fn as_char_ptr(&self) -> *const core::ffi::c_char {
|
@@ -299,6 +312,70 @@ impl CStr {
|
299 | 312 | pub fn to_cstring(&self) -> Result<CString, AllocError> {
|
300 | 313 | CString::try_from(self)
|
301 | 314 | }
|
| 315 | + |
| 316 | + /// Converts this [`CStr`] to its ASCII lower case equivalent in-place. |
| 317 | + /// |
| 318 | + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', |
| 319 | + /// but non-ASCII letters are unchanged. |
| 320 | + /// |
| 321 | + /// To return a new lowercased value without modifying the existing one, use |
| 322 | + /// [`to_ascii_lowercase()`]. |
| 323 | + /// |
| 324 | + /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase |
| 325 | + pub fn make_ascii_lowercase(&mut self) { |
| 326 | + // INVARIANT: This doesn't introduce or remove NUL bytes in the C |
| 327 | + // string. |
| 328 | + self.0.make_ascii_lowercase(); |
| 329 | + } |
| 330 | + |
| 331 | + /// Converts this [`CStr`] to its ASCII upper case equivalent in-place. |
| 332 | + /// |
| 333 | + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', |
| 334 | + /// but non-ASCII letters are unchanged. |
| 335 | + /// |
| 336 | + /// To return a new uppercased value without modifying the existing one, use |
| 337 | + /// [`to_ascii_uppercase()`]. |
| 338 | + /// |
| 339 | + /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase |
| 340 | + pub fn make_ascii_uppercase(&mut self) { |
| 341 | + // INVARIANT: This doesn't introduce or remove NUL bytes in the C |
| 342 | + // string. |
| 343 | + self.0.make_ascii_uppercase(); |
| 344 | + } |
| 345 | + |
| 346 | + /// Returns a copy of this [`CString`] where each character is mapped to its |
| 347 | + /// ASCII lower case equivalent. |
| 348 | + /// |
| 349 | + /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', |
| 350 | + /// but non-ASCII letters are unchanged. |
| 351 | + /// |
| 352 | + /// To lowercase the value in-place, use [`make_ascii_lowercase`]. |
| 353 | + /// |
| 354 | + /// [`make_ascii_lowercase`]: str::make_ascii_lowercase |
| 355 | + pub fn to_ascii_lowercase(&self) -> Result<CString, AllocError> { |
| 356 | + let mut s = self.to_cstring()?; |
| 357 | + |
| 358 | + s.make_ascii_lowercase(); |
| 359 | + |
| 360 | + Ok(s) |
| 361 | + } |
| 362 | + |
| 363 | + /// Returns a copy of this [`CString`] where each character is mapped to its |
| 364 | + /// ASCII upper case equivalent. |
| 365 | + /// |
| 366 | + /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', |
| 367 | + /// but non-ASCII letters are unchanged. |
| 368 | + /// |
| 369 | + /// To uppercase the value in-place, use [`make_ascii_uppercase`]. |
| 370 | + /// |
| 371 | + /// [`make_ascii_uppercase`]: str::make_ascii_uppercase |
| 372 | + pub fn to_ascii_uppercase(&self) -> Result<CString, AllocError> { |
| 373 | + let mut s = self.to_cstring()?; |
| 374 | + |
| 375 | + s.make_ascii_uppercase(); |
| 376 | + |
| 377 | + Ok(s) |
| 378 | + } |
302 | 379 | }
|
303 | 380 |
|
304 | 381 | impl fmt::Display for CStr {
|
@@ -764,6 +841,14 @@ impl Deref for CString {
|
764 | 841 | }
|
765 | 842 | }
|
766 | 843 |
|
| 844 | +impl DerefMut for CString { |
| 845 | + fn deref_mut(&mut self) -> &mut Self::Target { |
| 846 | + // SAFETY: A `CString` is always NUL-terminated and contains no other |
| 847 | + // NUL bytes. |
| 848 | + unsafe { CStr::from_bytes_with_nul_unchecked_mut(self.buf.as_mut_slice()) } |
| 849 | + } |
| 850 | +} |
| 851 | + |
767 | 852 | impl<'a> TryFrom<&'a CStr> for CString {
|
768 | 853 | type Error = AllocError;
|
769 | 854 |
|
|
0 commit comments