diff --git a/src/array.rs b/src/array.rs index 7fb3ec7..f008194 100644 --- a/src/array.rs +++ b/src/array.rs @@ -168,6 +168,7 @@ impl Clone for FixedArray { unsafe { Self::from_box_with_nonzero(ptr, self.len) } } + #[allow(clippy::assigning_clones)] fn clone_from(&mut self, source: &Self) { if self.len() == source.len() { self.clone_from_slice(source); diff --git a/src/inline.rs b/src/inline.rs index fadaf33..5d66fb7 100644 --- a/src/inline.rs +++ b/src/inline.rs @@ -1,3 +1,5 @@ +use core::mem::size_of; + use crate::ValidLength; #[cfg(feature = "typesize")] @@ -61,8 +63,12 @@ impl + AsMut<[u8]> + Default + TypeSize> InlineStrin StrRepr::default().as_ref().len() } - pub fn from_str(val: &str) -> Self { + pub fn from_str(val: &str) -> Option { let mut arr = StrRepr::default(); + if val.len() > size_of::() { + return None; + } + arr.as_mut()[..val.len()].copy_from_slice(val.as_bytes()); if val.len() != Self::max_len() { @@ -70,7 +76,7 @@ impl + AsMut<[u8]> + Default + TypeSize> InlineStrin arr.as_mut()[val.len()] = Self::TERMINATOR; } - Self { arr } + Some(Self { arr }) } pub fn len(&self) -> u8 { @@ -102,7 +108,7 @@ mod tests { Repr: Copy + AsRef<[u8]> + AsMut<[u8]> + Default + TypeSize, { let inline = InlineString::::from_str(original); - assert_eq!(original, inline.as_str()); + assert_eq!(original, inline.expect("should not overflow").as_str()); } fn check_roundtrip_repr + AsMut<[u8]> + Default + TypeSize>() { @@ -120,7 +126,7 @@ mod tests { } #[test] - #[should_panic(expected = "range end index 9 out of range for slice of length 8")] + #[should_panic(expected = "should not overflow")] fn check_overflow() { check_roundtrip::<[u8; 8]>("012345678"); } diff --git a/src/lib.rs b/src/lib.rs index 7c4aa5e..3b2e47c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,9 @@ #![cfg_attr(feature = "nightly", feature(portable_simd))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "std", allow(unused_imports))] #![warn(clippy::pedantic, clippy::as_conversions)] -#![allow(clippy::module_name_repetitions)] +#![allow(clippy::module_name_repetitions, unknown_lints)] extern crate alloc; diff --git a/src/string.rs b/src/string.rs index ee28a78..7e1fd3a 100644 --- a/src/string.rs +++ b/src/string.rs @@ -4,11 +4,11 @@ use alloc::{ string::{String, ToString}, sync::Arc, }; -use core::{borrow::Borrow, cmp::PartialEq, fmt::Write as _, hash::Hash}; +use core::{borrow::Borrow, fmt::Write as _, hash::Hash}; use crate::{ array::FixedArray, - inline::{get_heap_threshold, InlineString}, + inline::InlineString, length::{InvalidStrLength, SmallLen, ValidLength}, r#static::StaticStr, }; @@ -45,10 +45,10 @@ impl FixedString { Self::from_static_trunc("") } - /// # Panics - /// Panics if val does not fit in the heap threshold. - pub(crate) fn new_inline(val: &str) -> Self { - Self(FixedStringRepr::Inline(InlineString::from_str(val))) + pub(crate) fn new_inline(val: &str) -> Option { + InlineString::from_str(val) + .map(FixedStringRepr::Inline) + .map(Self) } /// Converts a `&'static str` into a [`FixedString`]. @@ -75,11 +75,11 @@ impl FixedString { /// See [`Self::from_string_trunc`] for truncation behaviour. #[must_use] pub fn from_str_trunc(val: &str) -> Self { - if val.len() <= get_heap_threshold::() { - return Self::new_inline(val); + if let Some(inline) = Self::new_inline(val) { + inline + } else { + Self::from_string_trunc(val.to_owned()) } - - Self::from_string_trunc(val.to_owned()) } /// Converts a [`String`] into a [`FixedString`], **truncating** if the value is larger than `LenT`'s maximum. @@ -166,6 +166,7 @@ impl Clone for FixedString { fn clone_from(&mut self, source: &Self) { match (&mut self.0, &source.0) { (FixedStringRepr::Heap(new), FixedStringRepr::Heap(src)) => new.clone_from(src), + #[allow(clippy::assigning_clones)] _ => *self = source.clone(), } } @@ -251,9 +252,8 @@ impl TryFrom> for FixedString { type Error = InvalidStrLength; fn try_from(value: Box) -> Result { - if value.len() <= get_heap_threshold::() { - let inner = InlineString::from_str(&value); - return Ok(Self(FixedStringRepr::Inline(inner))); + if let Some(inline) = Self::new_inline(&value) { + return Ok(inline); } match value.into_boxed_bytes().try_into() { @@ -329,11 +329,11 @@ impl<'de, LenT: ValidLength> serde::Deserialize<'de> for FixedString { } fn visit_str(self, val: &str) -> Result { - if val.len() <= get_heap_threshold::() { - return Ok(FixedString::new_inline(val)); + if let Some(inline) = FixedString::new_inline(val) { + Ok(inline) + } else { + FixedString::try_from(Box::from(val)).map_err(E::custom) } - - FixedString::try_from(Box::from(val)).map_err(E::custom) } fn visit_string(self, val: String) -> Result {