@@ -130,19 +130,28 @@ impl ast::String {
130
130
let text = self . text ( ) . as_str ( ) ;
131
131
let text = & text[ self . text_range_between_quotes ( ) ? - self . syntax ( ) . text_range ( ) . start ( ) ] ;
132
132
133
- let mut buf = String :: with_capacity ( text. len ( ) ) ;
133
+ let mut buf = String :: new ( ) ;
134
+ let mut text_iter = text. chars ( ) ;
134
135
let mut has_error = false ;
135
- unescape_literal ( text, Mode :: Str , & mut |_, unescaped_char| match unescaped_char {
136
- Ok ( c) => buf. push ( c) ,
137
- Err ( _) => has_error = true ,
136
+ unescape_literal ( text, Mode :: Str , & mut |char_range, unescaped_char| match (
137
+ unescaped_char,
138
+ buf. capacity ( ) == 0 ,
139
+ ) {
140
+ ( Ok ( c) , false ) => buf. push ( c) ,
141
+ ( Ok ( c) , true ) if Some ( c) == text_iter. next ( ) => ( ) ,
142
+ ( Ok ( c) , true ) => {
143
+ buf. reserve_exact ( text. len ( ) ) ;
144
+ buf. push_str ( & text[ ..char_range. start ] ) ;
145
+ buf. push ( c) ;
146
+ }
147
+ ( Err ( _) , _) => has_error = true ,
138
148
} ) ;
139
149
140
- if has_error {
141
- return None ;
150
+ match ( has_error, buf. capacity ( ) == 0 ) {
151
+ ( true , _) => None ,
152
+ ( false , true ) => Some ( Cow :: Borrowed ( text) ) ,
153
+ ( false , false ) => Some ( Cow :: Owned ( buf) ) ,
142
154
}
143
- // FIXME: don't actually allocate for borrowed case
144
- let res = if buf == text { Cow :: Borrowed ( text) } else { Cow :: Owned ( buf) } ;
145
- Some ( res)
146
155
}
147
156
148
157
pub fn quote_offsets ( & self ) -> Option < QuoteOffsets > {
0 commit comments