From 0519a4253f01c975eb399379425f4c3e74eb4977 Mon Sep 17 00:00:00 2001 From: Dominic Burkart Date: Sun, 4 Dec 2022 23:58:19 +0100 Subject: [PATCH 1/3] add const function to get &str from ArrayString --- src/array_string.rs | 22 ++++++++++++++++------ tests/tests.rs | 8 +++++++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index 5c3414f..0c27199 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 @@ -466,7 +476,7 @@ impl PartialEq> for str } } -impl Eq for ArrayString +impl Eq for ArrayString { } impl Hash for ArrayString @@ -587,7 +597,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..9c87a88 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -545,7 +545,13 @@ fn test_string() { let tmut: &mut str = &mut t; assert_eq!(tmut, "ab"); + // test ArrayString -> &str in const + const CONST_T: ArrayString<2> = ArrayString::<2>::new_const(); + const CONST_S: &str = CONST_T.as_str_const(); + assert_eq!(CONST_S, ""); + // Test Error trait / try + let t = || -> Result<(), Box> { let mut t = ArrayString::<2>::new(); t.try_push_str(text)?; @@ -790,4 +796,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 +} From f1de28593c6a81813d59f8d30a0b5b3bd2b54382 Mon Sep 17 00:00:00 2001 From: Dominic Burkart Date: Mon, 5 Dec 2022 00:16:39 +0100 Subject: [PATCH 2/3] share code across both functions --- src/array_string.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/array_string.rs b/src/array_string.rs index 0c27199..f717b14 100644 --- a/src/array_string.rs +++ b/src/array_string.rs @@ -436,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() } } From c505b0e8fb7ea69272e4edd7008aba9c7b37dd7e Mon Sep 17 00:00:00 2001 From: Dominic Burkart Date: Thu, 8 Dec 2022 21:43:11 +0100 Subject: [PATCH 3/3] use const fn in test --- tests/tests.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/tests.rs b/tests/tests.rs index 9c87a88..33b91f6 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -545,10 +545,16 @@ fn test_string() { let tmut: &mut str = &mut t; assert_eq!(tmut, "ab"); - // test ArrayString -> &str in const - const CONST_T: ArrayString<2> = ArrayString::<2>::new_const(); - const CONST_S: &str = CONST_T.as_str_const(); - assert_eq!(CONST_S, ""); + // 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