Skip to content

Commit 30d4c15

Browse files
author
Daniel Bloom
committed
feat+refactor: Maximize const
1 parent 812c83a commit 30d4c15

File tree

5 files changed

+101
-174
lines changed

5 files changed

+101
-174
lines changed

src/array_string.rs

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<const CAP: usize> ArrayString<CAP>
6262
/// assert_eq!(&string[..], "foo");
6363
/// assert_eq!(string.capacity(), 16);
6464
/// ```
65-
pub fn new() -> ArrayString<CAP> {
65+
pub const fn new() -> ArrayString<CAP> {
6666
assert_capacity_limit!(CAP);
6767
unsafe {
6868
ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 }
@@ -105,10 +105,12 @@ impl<const CAP: usize> ArrayString<CAP>
105105
/// assert_eq!(string.len(), 3);
106106
/// assert_eq!(string.capacity(), 3);
107107
/// ```
108-
pub fn from(s: &str) -> Result<Self, CapacityError<&str>> {
108+
pub const fn from(s: &str) -> Result<Self, CapacityError<&str>> {
109109
let mut arraystr = Self::new();
110-
arraystr.try_push_str(s)?;
111-
Ok(arraystr)
110+
match arraystr.try_push_str(s) {
111+
Ok(()) => Ok(arraystr),
112+
Err(e) => Err(e),
113+
}
112114
}
113115

114116
/// Create a new `ArrayString` from a byte string literal.
@@ -120,9 +122,12 @@ impl<const CAP: usize> ArrayString<CAP>
120122
///
121123
/// let string = ArrayString::from_byte_string(b"hello world").unwrap();
122124
/// ```
123-
pub fn from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error> {
124-
let len = str::from_utf8(b)?.len();
125-
debug_assert_eq!(len, CAP);
125+
pub const fn from_byte_string(b: &[u8; CAP]) -> Result<Self, Utf8Error> {
126+
let len = match str::from_utf8(b) {
127+
Ok(str) => str.len(),
128+
Err(e) => return Err(e),
129+
};
130+
debug_assert!(len == CAP);
126131
let mut vec = Self::new();
127132
unsafe {
128133
(b as *const [u8; CAP] as *const [MaybeUninit<u8>; CAP])
@@ -142,7 +147,7 @@ impl<const CAP: usize> ArrayString<CAP>
142147
/// assert_eq!(string.len(), 16);
143148
/// ```
144149
#[inline]
145-
pub fn zero_filled() -> Self {
150+
pub const fn zero_filled() -> Self {
146151
assert_capacity_limit!(CAP);
147152
// SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and
148153
// `zeroed` fully fills the array with nulls.
@@ -227,7 +232,7 @@ impl<const CAP: usize> ArrayString<CAP>
227232
/// assert_eq!(&string[..], "ab");
228233
/// assert_eq!(overflow.unwrap_err().element(), 'c');
229234
/// ```
230-
pub fn try_push(&mut self, c: char) -> Result<(), CapacityError<char>> {
235+
pub const fn try_push(&mut self, c: char) -> Result<(), CapacityError<char>> {
231236
let len = self.len();
232237
unsafe {
233238
let ptr = self.as_mut_ptr().add(len);
@@ -281,7 +286,7 @@ impl<const CAP: usize> ArrayString<CAP>
281286
/// assert_eq!(overflow1.unwrap_err().element(), "bc");
282287
/// assert_eq!(overflow2.unwrap_err().element(), "ef");
283288
/// ```
284-
pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> {
289+
pub const fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> {
285290
if s.len() > self.capacity() - self.len() {
286291
return Err(CapacityError::new(s));
287292
}
@@ -340,7 +345,7 @@ impl<const CAP: usize> ArrayString<CAP>
340345
/// ```
341346
pub fn truncate(&mut self, new_len: usize) {
342347
if new_len <= self.len() {
343-
assert!(self.is_char_boundary(new_len));
348+
assert!(self.as_str().is_char_boundary(new_len));
344349
unsafe {
345350
// In libstd truncate is called on the underlying vector,
346351
// which in turns drops each element.
@@ -388,7 +393,7 @@ impl<const CAP: usize> ArrayString<CAP>
388393
}
389394

390395
/// Make the string empty.
391-
pub fn clear(&mut self) {
396+
pub const fn clear(&mut self) {
392397
unsafe {
393398
self.set_len(0);
394399
}
@@ -401,29 +406,36 @@ impl<const CAP: usize> ArrayString<CAP>
401406
///
402407
/// This method uses *debug assertions* to check the validity of `length`
403408
/// and may use other debug assertions.
404-
pub unsafe fn set_len(&mut self, length: usize) {
409+
pub const unsafe fn set_len(&mut self, length: usize) {
405410
// type invariant that capacity always fits in LenUint
406411
debug_assert!(length <= self.capacity());
407412
self.len = length as LenUint;
408413
}
409414

410415
/// Return a string slice of the whole `ArrayString`.
411-
pub fn as_str(&self) -> &str {
412-
self
416+
pub const fn as_str(&self) -> &str {
417+
unsafe {
418+
let sl = slice::from_raw_parts(self.as_ptr(), self.len());
419+
str::from_utf8_unchecked(sl)
420+
}
413421
}
414422

415423
/// Return a mutable string slice of the whole `ArrayString`.
416-
pub fn as_mut_str(&mut self) -> &mut str {
417-
self
424+
pub const fn as_mut_str(&mut self) -> &mut str {
425+
unsafe {
426+
let len = self.len();
427+
let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len);
428+
str::from_utf8_unchecked_mut(sl)
429+
}
418430
}
419431

420432
/// Return a raw pointer to the string's buffer.
421-
pub fn as_ptr(&self) -> *const u8 {
433+
pub const fn as_ptr(&self) -> *const u8 {
422434
self.xs.as_ptr() as *const u8
423435
}
424436

425437
/// Return a raw mutable pointer to the string's buffer.
426-
pub fn as_mut_ptr(&mut self) -> *mut u8 {
438+
pub const fn as_mut_ptr(&mut self) -> *mut u8 {
427439
self.xs.as_mut_ptr() as *mut u8
428440
}
429441
}
@@ -433,22 +445,15 @@ impl<const CAP: usize> Deref for ArrayString<CAP>
433445
type Target = str;
434446
#[inline]
435447
fn deref(&self) -> &str {
436-
unsafe {
437-
let sl = slice::from_raw_parts(self.as_ptr(), self.len());
438-
str::from_utf8_unchecked(sl)
439-
}
448+
self.as_str()
440449
}
441450
}
442451

443452
impl<const CAP: usize> DerefMut for ArrayString<CAP>
444453
{
445454
#[inline]
446455
fn deref_mut(&mut self) -> &mut str {
447-
unsafe {
448-
let len = self.len();
449-
let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len);
450-
str::from_utf8_unchecked_mut(sl)
451-
}
456+
self.as_mut_str()
452457
}
453458
}
454459

0 commit comments

Comments
 (0)