11use alloc:: {
22 borrow:: { Cow , ToOwned } ,
33 boxed:: Box ,
4- string:: { String } ,
4+ string:: String ,
55 sync:: Arc ,
66} ;
77use core:: { borrow:: Borrow , hash:: Hash , str:: FromStr } ;
@@ -35,7 +35,7 @@ fn truncate_str(string: &str, max_len: usize) -> &str {
3535 }
3636 }
3737
38- unreachable ! ( "Len 0 is a char boundary" )
38+ unreachable ! ( "Len 0 is a char boundary" ) ;
3939}
4040
4141/// A fixed size String with length provided at creation denoted in [`ValidLength`], by default [`u32`].
@@ -61,10 +61,13 @@ impl<LenT: ValidLength> FixedString<LenT> {
6161 /// This method will not allocate, or copy the string data.
6262 ///
6363 /// See [`Self::from_string_trunc`] for truncation behaviour.
64- pub fn from_static_trunc ( val : & ' static str ) -> Self {
65- Self ( FixedStringRepr :: Static ( StaticStr :: from_static_str (
66- truncate_str ( val, LenT :: MAX . to_usize ( ) ) ,
67- ) ) )
64+ pub fn from_static_trunc ( mut val : & ' static str ) -> Self {
65+ let max_len = LenT :: MAX . to_usize ( ) ;
66+ if val. len ( ) > max_len {
67+ val = truncate_str ( val, max_len) ;
68+ }
69+
70+ Self ( FixedStringRepr :: Static ( StaticStr :: from_static_str ( val) ) )
6871 }
6972
7073 /// Converts a `&str` into a [`FixedString`], allocating if the value cannot fit "inline".
@@ -93,7 +96,7 @@ impl<LenT: ValidLength> FixedString<LenT> {
9396 /// For lossless fallible conversion, convert to [`Box<str>`] using [`String::into_boxed_str`] and use [`TryFrom`].
9497 #[ must_use]
9598 pub fn from_string_trunc ( str : String ) -> Self {
96- match str. into_boxed_str ( ) . try_into ( ) {
99+ match str. try_into ( ) {
97100 Ok ( val) => val,
98101 Err ( err) => Self :: from_string_trunc ( truncate_string ( err, LenT :: MAX . to_usize ( ) ) ) ,
99102 }
@@ -438,6 +441,29 @@ mod test {
438441 }
439442 }
440443
444+ // primarily intended to ensure no hangs occur
445+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
446+ fn check_u32_partial_roundtrip_generic ( to_fixed : fn ( String ) -> FixedString < u32 > ) {
447+ for i in 0 ..=400u32 {
448+ let original = "a" . repeat ( i as usize ) ;
449+ let fixed = to_fixed ( original) ;
450+
451+ assert ! ( fixed. bytes( ) . all( |c| c == b'a' ) ) ;
452+ assert_eq ! ( fixed. len( ) , i) ;
453+
454+ if !fixed. is_static ( ) {
455+ assert_eq ! ( fixed. is_inline( ) , fixed. len( ) <= 12 ) ;
456+ }
457+ }
458+ }
459+
460+ fn check_default_generic < LenT : ValidLength > ( ) {
461+ let fixed = FixedString :: < LenT > :: default ( ) ;
462+
463+ assert ! ( fixed. is_static( ) ) ;
464+ assert_eq ! ( fixed. as_str( ) , "" ) ;
465+ }
466+
441467 #[ test]
442468 fn test_truncating_behaviour ( ) {
443469 const STR : & str = "______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________🦀" ;
@@ -482,6 +508,23 @@ mod test {
482508 } ) ;
483509 }
484510
511+ #[ test]
512+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
513+ fn check_u32_partial_roundtrip ( ) {
514+ check_u32_partial_roundtrip_generic ( |original| {
515+ FixedString :: < u32 > :: try_from ( original) . unwrap ( )
516+ } ) ;
517+ }
518+
519+ #[ test]
520+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
521+ fn check_u32_partial_roundtrip_static ( ) {
522+ check_u32_partial_roundtrip_generic ( |original| {
523+ let static_str = Box :: leak ( original. into_boxed_str ( ) ) ;
524+ FixedString :: from_static_trunc ( static_str)
525+ } ) ;
526+ }
527+
485528 #[ test]
486529 #[ cfg( feature = "serde" ) ]
487530 fn check_u8_roundtrip_serde ( ) {
@@ -504,6 +547,22 @@ mod test {
504547 } ) ;
505548 }
506549
550+ #[ test]
551+ fn check_default_u8 ( ) {
552+ check_default_generic :: < u8 > ( ) ;
553+ }
554+
555+ #[ test]
556+ fn check_default_u16 ( ) {
557+ check_default_generic :: < u16 > ( ) ;
558+ }
559+
560+ #[ test]
561+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
562+ fn check_default_u32 ( ) {
563+ check_default_generic :: < u32 > ( ) ;
564+ }
565+
507566 #[ test]
508567 fn check_sizes ( ) {
509568 type DoubleOpt < T > = Option < Option < T > > ;
0 commit comments