@@ -2,7 +2,7 @@ use alloc::{
22 borrow:: { Cow } ,
33 boxed:: Box ,
44 rc:: Rc ,
5- string:: { String } ,
5+ string:: String ,
66 sync:: Arc ,
77} ;
88use core:: { borrow:: Borrow , hash:: Hash , str:: FromStr } ;
@@ -36,7 +36,7 @@ fn truncate_str(string: &str, max_len: usize) -> &str {
3636 }
3737 }
3838
39- unreachable ! ( "Len 0 is a char boundary" )
39+ unreachable ! ( "Len 0 is a char boundary" ) ;
4040}
4141
4242/// A fixed size String with length provided at creation denoted in [`ValidLength`], by default [`u32`].
@@ -62,10 +62,13 @@ impl<LenT: ValidLength> FixedString<LenT> {
6262 /// This method will not allocate, or copy the string data.
6363 ///
6464 /// See [`Self::from_string_trunc`] for truncation behaviour.
65- pub fn from_static_trunc ( val : & ' static str ) -> Self {
66- Self ( FixedStringRepr :: Static ( StaticStr :: from_static_str (
67- truncate_str ( val, LenT :: MAX . to_usize ( ) ) ,
68- ) ) )
65+ pub fn from_static_trunc ( mut val : & ' static str ) -> Self {
66+ let max_len = LenT :: MAX . to_usize ( ) ;
67+ if val. len ( ) > max_len {
68+ val = truncate_str ( val, max_len) ;
69+ }
70+
71+ Self ( FixedStringRepr :: Static ( StaticStr :: from_static_str ( val) ) )
6972 }
7073
7174 /// Converts a string into a [`FixedString`], **truncating** if the value is larger than `LenT`'s maximum.
@@ -458,6 +461,29 @@ mod test {
458461 }
459462 }
460463
464+ // primarily intended to ensure no hangs occur
465+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
466+ fn check_u32_partial_roundtrip_generic ( to_fixed : fn ( String ) -> FixedString < u32 > ) {
467+ for i in 0 ..=400u32 {
468+ let original = "a" . repeat ( i as usize ) ;
469+ let fixed = to_fixed ( original) ;
470+
471+ assert ! ( fixed. bytes( ) . all( |c| c == b'a' ) ) ;
472+ assert_eq ! ( fixed. len( ) , i) ;
473+
474+ if !fixed. is_static ( ) {
475+ assert_eq ! ( fixed. is_inline( ) , fixed. len( ) <= 12 ) ;
476+ }
477+ }
478+ }
479+
480+ fn check_default_generic < LenT : ValidLength > ( ) {
481+ let fixed = FixedString :: < LenT > :: default ( ) ;
482+
483+ assert ! ( fixed. is_static( ) ) ;
484+ assert_eq ! ( fixed. as_str( ) , "" ) ;
485+ }
486+
461487 #[ test]
462488 fn test_truncating_behaviour ( ) {
463489 const STR : & str = "______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________🦀" ;
@@ -502,6 +528,23 @@ mod test {
502528 } ) ;
503529 }
504530
531+ #[ test]
532+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
533+ fn check_u32_partial_roundtrip ( ) {
534+ check_u32_partial_roundtrip_generic ( |original| {
535+ FixedString :: < u32 > :: try_from ( original) . unwrap ( )
536+ } ) ;
537+ }
538+
539+ #[ test]
540+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
541+ fn check_u32_partial_roundtrip_static ( ) {
542+ check_u32_partial_roundtrip_generic ( |original| {
543+ let static_str = Box :: leak ( original. into_boxed_str ( ) ) ;
544+ FixedString :: from_static_trunc ( static_str)
545+ } ) ;
546+ }
547+
505548 #[ test]
506549 #[ cfg( feature = "serde" ) ]
507550 fn check_u8_roundtrip_serde ( ) {
@@ -524,6 +567,22 @@ mod test {
524567 } ) ;
525568 }
526569
570+ #[ test]
571+ fn check_default_u8 ( ) {
572+ check_default_generic :: < u8 > ( ) ;
573+ }
574+
575+ #[ test]
576+ fn check_default_u16 ( ) {
577+ check_default_generic :: < u16 > ( ) ;
578+ }
579+
580+ #[ test]
581+ #[ cfg( any( target_pointer_width = "64" , target_pointer_width = "32" ) ) ]
582+ fn check_default_u32 ( ) {
583+ check_default_generic :: < u32 > ( ) ;
584+ }
585+
527586 #[ test]
528587 fn check_sizes ( ) {
529588 type DoubleOpt < T > = Option < Option < T > > ;
0 commit comments