diff --git a/src/array_string.rs b/src/array_string.rs index 5c3414f..f717b14 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -296,7 +296,7 @@ impl ArrayString /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); @@ -336,7 +336,7 @@ impl ArrayString pub fn truncate(&mut self, new_len: usize) { if new_len <= self.len() { assert!(self.is_char_boundary(new_len)); - unsafe { + unsafe { // In libstd truncate is called on the underlying vector, // which in turns drops each element. // As we know we don't have to worry about Drop, @@ -356,7 +356,7 @@ impl ArrayString /// /// ``` /// use arrayvec::ArrayString; - /// + /// /// let mut s = ArrayString::<3>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); @@ -412,13 +412,23 @@ impl ArrayString self } - fn as_ptr(&self) -> *const u8 { + const fn as_ptr(&self) -> *const u8 { self.xs.as_ptr() as *const u8 } fn as_mut_ptr(&mut self) -> *mut u8 { self.xs.as_mut_ptr() as *mut u8 } + + /// Provide a &str in constant contexts where the dereference + /// trait is not available. + #[inline] + pub const fn as_str_const(&self) -> &str { + unsafe { + let sl = slice::from_raw_parts(self.as_ptr(), self.len()); + str::from_utf8_unchecked(sl) + } + } } impl Deref for ArrayString @@ -426,10 +436,7 @@ impl Deref for ArrayString type Target = str; #[inline] fn deref(&self) -> &str { - unsafe { - let sl = slice::from_raw_parts(self.as_ptr(), self.len()); - str::from_utf8_unchecked(sl) - } + self.as_str_const() } } @@ -466,7 +473,7 @@ impl PartialEq> for str } } -impl Eq for ArrayString +impl Eq for ArrayString { } impl Hash for ArrayString @@ -587,7 +594,7 @@ impl Serialize for ArrayString #[cfg(feature="serde")] /// Requires crate feature `"serde"` -impl<'de, const CAP: usize> Deserialize<'de> for ArrayString +impl<'de, const CAP: usize> Deserialize<'de> for ArrayString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> diff --git a/tests/tests.rs b/tests/tests.rs index 2f8a5ef..33b91f6 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -545,7 +545,19 @@ fn test_string() { let tmut: &mut str = &mut t; assert_eq!(tmut, "ab"); + // test ArrayString -> &str in const fn + let arr_str = ArrayString::<2>::from("ab").unwrap(); + const fn get_second_char(a: ArrayString<2>) -> char { + match a.as_str_const().as_bytes() { + [_char1, char2] => (*char2) as char, + [_char1] => panic!(), + _ => unreachable!(), + } + } + assert_eq!(get_second_char(arr_str), 'b'); + // Test Error trait / try + let t = || -> Result<(), Box> { let mut t = ArrayString::<2>::new(); t.try_push_str(text)?; @@ -790,4 +802,4 @@ fn test_arraystring_zero_filled_has_some_sanity_checks() { let string = ArrayString::<4>::zero_filled(); assert_eq!(string.as_str(), "\0\0\0\0"); assert_eq!(string.len(), 4); -} \ No newline at end of file +}