@@ -594,6 +594,41 @@ where
594594 }
595595 }
596596
597+ /// Like `from_utf8_lossy`, but this honors COOP_PREFERRED.
598+ #[ unstable( feature = "compile_check_struct_with_const_generic_added_associated_function" , reason = "confirm_or_fix_the_function_name" , issue = "none" ) ]
599+ pub fn from_utf8_lossy_coop_or_not ( v : & [ u8 ] ) -> Cow < ' _ , str , COOP_PREFERRED > {
600+ let mut iter = Utf8Chunks :: new ( v) ;
601+
602+ let first_valid = if let Some ( chunk) = iter. next ( ) {
603+ let valid = chunk. valid ( ) ;
604+ if chunk. invalid ( ) . is_empty ( ) {
605+ debug_assert_eq ! ( valid. len( ) , v. len( ) ) ;
606+ return Cow :: Borrowed ( valid) ;
607+ }
608+ valid
609+ } else {
610+ return Cow :: Borrowed ( "" ) ;
611+ } ;
612+
613+ const REPLACEMENT : & str = "\u{FFFD} " ;
614+
615+ #[ allow( unused_braces) ]
616+ let mut res = String :: < COOP_PREFERRED > :: with_capacity ( v. len ( ) ) ;
617+ res. push_str ( first_valid) ;
618+ res. push_str ( REPLACEMENT ) ;
619+
620+ for chunk in iter {
621+ res. push_str ( chunk. valid ( ) ) ;
622+ if !chunk. invalid ( ) . is_empty ( ) {
623+ res. push_str ( REPLACEMENT ) ;
624+ }
625+ }
626+
627+ Cow :: Owned ( res)
628+ }
629+ }
630+
631+ impl String {
597632 /// Converts a slice of bytes to a string, including invalid characters.
598633 ///
599634 /// Strings are made of bytes ([`u8`]), and a slice of bytes
@@ -643,39 +678,22 @@ where
643678 ///
644679 /// assert_eq!("Hello �World", output);
645680 /// ```
681+ /// @FIXME Should this return Cow<'_, str, false> instead, so it's both
682+ /// - backwards compatible, and
683+ /// - independent of DEFAULT_COOP_PREFERRED (for backwards compatbility)? But `String` (and others) use default, too.
646684 #[ must_use]
647685 #[ cfg( not( no_global_oom_handling) ) ]
648686 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
649- pub fn from_utf8_lossy ( v : & [ u8 ] ) -> Cow < ' _ , str , COOP_PREFERRED > {
650- let mut iter = Utf8Chunks :: new ( v) ;
651-
652- let first_valid = if let Some ( chunk) = iter. next ( ) {
653- let valid = chunk. valid ( ) ;
654- if chunk. invalid ( ) . is_empty ( ) {
655- debug_assert_eq ! ( valid. len( ) , v. len( ) ) ;
656- return Cow :: Borrowed ( valid) ;
657- }
658- valid
659- } else {
660- return Cow :: Borrowed ( "" ) ;
661- } ;
662-
663- const REPLACEMENT : & str = "\u{FFFD} " ;
664-
665- let mut res = String :: < COOP_PREFERRED > :: with_capacity ( v. len ( ) ) ;
666- res. push_str ( first_valid) ;
667- res. push_str ( REPLACEMENT ) ;
668-
669- for chunk in iter {
670- res. push_str ( chunk. valid ( ) ) ;
671- if !chunk. invalid ( ) . is_empty ( ) {
672- res. push_str ( REPLACEMENT ) ;
673- }
674- }
675-
676- Cow :: Owned ( res)
687+ #[ allow( unused_braces) ]
688+ pub fn from_utf8_lossy ( v : & [ u8 ] ) -> Cow < ' _ , str , { DEFAULT_COOP_PREFERRED ! ( ) } > {
689+ String :: < { DEFAULT_COOP_PREFERRED ! ( ) } > :: from_utf8_lossy_coop_or_not ( v)
677690 }
691+ }
678692
693+ impl < const COOP_PREFERRED : bool > String < COOP_PREFERRED >
694+ where
695+ [ ( ) ; core:: alloc:: co_alloc_metadata_num_slots_with_preference :: < Global > ( COOP_PREFERRED ) ] : ,
696+ {
679697 /// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`]
680698 /// if `v` contains any invalid data.
681699 ///
0 commit comments