@@ -62,9 +62,10 @@ use crate::alloc::Allocator;
6262use crate :: borrow:: { Cow , ToOwned } ;
6363use crate :: boxed:: Box ;
6464use crate :: collections:: TryReserveError ;
65- use crate :: str:: { self , Chars , Utf8Error , from_utf8_unchecked_mut} ;
65+ use crate :: str:: { self , Chars , Utf8Error , from_utf8_unchecked_mut, CharIndices } ;
6666#[ cfg( not( no_global_oom_handling) ) ]
6767use crate :: str:: { FromStr , from_boxed_utf8_unchecked} ;
68+ use crate :: vec;
6869use crate :: vec:: Vec ;
6970
7071/// A UTF-8–encoded, growable string.
@@ -3094,6 +3095,90 @@ impl fmt::Write for String {
30943095 }
30953096}
30963097
3098+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3099+ pub struct IntoChars {
3100+ bytes : Vec < u8 > ,
3101+ }
3102+
3103+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3104+ impl fmt:: Debug for IntoChars {
3105+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
3106+ f. debug_tuple ( "IntoChars" ) . field ( & self . as_str ( ) ) . finish ( )
3107+ }
3108+ }
3109+
3110+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3111+ impl IntoChars {
3112+ pub fn as_str ( & self ) -> & str {
3113+ // SAFETY: `bytes` is a valid UTF-8 string.
3114+ unsafe { str:: from_utf8_unchecked ( self . bytes . as_slice ( ) ) }
3115+ }
3116+
3117+ fn iter ( & self ) -> CharIndices {
3118+ self . as_str ( ) . char_indices ( )
3119+ }
3120+ }
3121+
3122+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3123+ impl AsRef < str > for IntoChars {
3124+ fn as_ref ( & self ) -> & str {
3125+ self . as_str ( )
3126+ }
3127+ }
3128+
3129+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3130+ impl AsRef < [ u8 ] > for IntoChars {
3131+ fn as_ref ( & self ) -> & [ u8 ] {
3132+ self . bytes . as_slice ( )
3133+ }
3134+ }
3135+
3136+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3137+ impl Iterator for IntoChars {
3138+ type Item = char ;
3139+
3140+ #[ inline]
3141+ fn next ( & mut self ) -> Option < char > {
3142+ let mut iter = self . iter ( ) ;
3143+ match iter. next ( ) {
3144+ None => None ,
3145+ Some ( ( _, ch) ) => {
3146+ let offset = iter. offset ( ) ;
3147+ drop ( self . bytes . drain ( ..offset) ) ;
3148+ Some ( ch)
3149+ }
3150+ }
3151+ }
3152+
3153+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
3154+ self . iter ( ) . size_hint ( )
3155+ }
3156+
3157+ #[ inline]
3158+ fn last ( mut self ) -> Option < char > {
3159+ self . next_back ( )
3160+ }
3161+ }
3162+
3163+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3164+ impl DoubleEndedIterator for IntoChars {
3165+ #[ inline]
3166+ fn next_back ( & mut self ) -> Option < char > {
3167+ let mut iter = self . iter ( ) ;
3168+ match iter. next_back ( ) {
3169+ None => None ,
3170+ Some ( ( idx, ch) ) => {
3171+ self . bytes . truncate ( idx) ;
3172+ Some ( ch)
3173+ }
3174+ }
3175+ }
3176+ }
3177+
3178+ #[ unstable( feature = "into_chars" , reason = "new API" , issue="0" ) ]
3179+ impl FusedIterator for IntoChars { }
3180+
3181+
30973182/// A draining iterator for `String`.
30983183///
30993184/// This struct is created by the [`drain`] method on [`String`]. See its
0 commit comments