|
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