@@ -60,45 +60,38 @@ pub fn escape_word_array_content(
6060 const TARGET_OPEN : char = '[' ;
6161 const TARGET_CLOSE : char = ']' ;
6262
63- let chars: Vec < char > = content. chars ( ) . collect ( ) ;
63+ let mut chars = content. chars ( ) . peekable ( ) ;
6464 let mut output = String :: new ( ) ;
65- let mut i = 0 ;
6665
67- while i < chars. len ( ) {
68- let c = chars[ i] ;
69-
70- if c == '\\' && i + 1 < chars. len ( ) {
71- let next = chars[ i + 1 ] ;
72- if next == '\\' {
73- // Escaped backslash, keep both
74- output. push ( '\\' ) ;
75- output. push ( '\\' ) ;
76- i += 2 ;
77- } else if next == orig_open_delim || next == orig_close_delim {
78- // Original delimiter was escaped - unescape unless it's also a target delimiter
79- if next == TARGET_OPEN || next == TARGET_CLOSE {
66+ while let Some ( c) = chars. next ( ) {
67+ if c == '\\' {
68+ if let Some ( & next) = chars. peek ( ) {
69+ if next == '\\' {
70+ // Escaped backslash, keep both
71+ output. push ( '\\' ) ;
72+ output. push ( '\\' ) ;
73+ } else if next == orig_open_delim || next == orig_close_delim {
74+ // Original delimiter was escaped - unescape unless it's also a target delimiter
75+ if next == TARGET_OPEN || next == TARGET_CLOSE {
76+ output. push ( '\\' ) ;
77+ }
78+ output. push ( next) ;
79+ } else if next == TARGET_OPEN || next == TARGET_CLOSE {
80+ // Already escaped target delimiter, keep it
8081 output. push ( '\\' ) ;
82+ output. push ( next) ;
83+ } else {
84+ output. push ( '\\' ) ;
85+ output. push ( next) ;
8186 }
82- output. push ( next) ;
83- i += 2 ;
84- } else if next == TARGET_OPEN || next == TARGET_CLOSE {
85- // Already escaped target delimiter, keep it
86- output. push ( '\\' ) ;
87- output. push ( next) ;
88- i += 2 ;
89- } else {
90- output. push ( '\\' ) ;
91- output. push ( next) ;
92- i += 2 ;
87+ chars. next ( ) ;
9388 }
9489 } else if c == TARGET_OPEN || c == TARGET_CLOSE {
9590 // Unescaped target delimiter needs escaping
9691 output. push ( '\\' ) ;
9792 output. push ( c) ;
98- i += 1 ;
9993 } else {
10094 output. push ( c) ;
101- i += 1 ;
10295 }
10396 }
10497
@@ -110,75 +103,72 @@ fn escape_string(content: &str, opening_delim: char, closing_delim: char) -> Str
110103 return content. to_string ( ) ;
111104 }
112105
113- let chars = content. chars ( ) . collect :: < Vec < char > > ( ) ;
114- let mut i = 0 ;
115-
106+ let mut chars = content. chars ( ) . peekable ( ) ;
116107 let mut output = String :: new ( ) ;
117108
118- while let Some ( i_char ) = chars. get ( i ) {
119- match i_char {
109+ while let Some ( c ) = chars. next ( ) {
110+ match c {
120111 '"' => {
121112 output. push ( '\\' ) ;
122113 }
123114 '\\' => {
124- if let Some ( next_char) = chars. get ( i + 1 ) {
115+ if let Some ( & next_char) = chars. peek ( ) {
125116 match next_char {
126117 '\'' => {
127118 // String#inspect strips the leading backslash from \', despite it being a valid
128119 // escape character in double-quoted strings as well. Leaving the behavior the same
129120 // for consistency with the previous behavior.
130121 output. push ( '\'' ) ;
131- i += 2 ;
122+ chars . next ( ) ;
132123 continue ;
133124 }
134125 // '\\' is considered an escape sequence in both single and double quoted strings
135126 // and thus we don't need to "double-escape" it to "\\\\"
136127 '\\' => {
137128 output. push_str ( "\\ \\ " ) ;
138- i += 2 ;
129+ chars . next ( ) ;
139130 continue ;
140131 }
141132 // '\"' is a slash char and a double-quote char, not an escaped double-quote,
142133 // so here we print an escaped slash character and then an escaped quote character: `"\\\""`
143134 '"' => {
144135 output. push_str ( "\\ \\ \\ \" " ) ;
145- i += 2 ;
136+ chars . next ( ) ;
146137 continue ;
147138 }
148139 delim_char
149- if ( * delim_char == opening_delim
150- || * delim_char == closing_delim)
140+ if ( delim_char == opening_delim || delim_char == closing_delim)
151141 // We only care about the "non-standard" delimiters like %() etc.
152142 // For single-quoted strings, these characters should *not* be treated as escape sequences.
153143 && opening_delim != '\'' =>
154144 {
155145 // In percent-strings, the opening and closing delimiters can be escaped to prevent terminating the string.
156- output. push ( * delim_char) ;
157- i += 2 ;
146+ output. push ( delim_char) ;
147+ chars . next ( ) ;
158148 continue ;
159149 }
160150 // For everything else, this is not an escape sequnce, so we need to
161151 // escape the slash and then print the next character.
162152 _ => {
163153 output. push ( '\\' ) ;
164154 output. push ( '\\' ) ;
165- output. push ( * next_char) ;
166- i += 2 ;
155+ output. push ( next_char) ;
156+ chars . next ( ) ;
167157 continue ;
168158 }
169159 }
170160 }
171161 }
172162 '#' => {
173- if let Some ( next_char) = chars. get ( i + 1 ) {
163+ if let Some ( & next_char) = chars. peek ( ) {
174164 match next_char {
175165 // These are shorthands for embedded variables when double-quoted,
176166 // e.g. "#@foo", "#$GLOBAL", and "#{1}", so they must be escaped
177167 '$' | '@' | '{' => {
178168 output. push ( '\\' ) ;
179- output. push ( * i_char ) ;
180- output. push ( * next_char) ;
181- i += 2 ;
169+ output. push ( c ) ;
170+ output. push ( next_char) ;
171+ chars . next ( ) ;
182172 continue ;
183173 }
184174 _ => { }
@@ -187,9 +177,7 @@ fn escape_string(content: &str, opening_delim: char, closing_delim: char) -> Str
187177 }
188178 _ => { }
189179 } ;
190-
191- output. push ( * i_char) ;
192- i += 1 ;
180+ output. push ( c) ;
193181 }
194182
195183 output
0 commit comments