@@ -115,42 +115,74 @@ impl<'a> FormatArguments<'a> {
115
115
}
116
116
}
117
117
118
- fn get_num < T > ( os : & OsStr ) -> T
118
+ // Parse an OsStr that we know to start with a '/"
119
+ fn parse_quote_start < T > ( os : & OsStr ) -> Result < T , ExtendedParserError < T > >
119
120
where
120
121
T : ExtendedParser + From < u8 > + From < u32 > + Default ,
121
122
{
122
- // FIXME: Remove unwrap
123
- let s = os_str_as_bytes ( os) . unwrap ( ) ;
124
- // Check if the string begins with a quote, and is therefore a literal
125
- if let Some ( ( & first, bytes) ) = s. split_first ( ) {
126
- if ( first == b'"' || first == b'\'' ) && !bytes. is_empty ( ) {
127
- let ( val, len) = if let Some ( c) = bytes
128
- . utf8_chunks ( )
129
- . next ( )
130
- . expect ( "bytes should not be empty" )
131
- . valid ( )
132
- . chars ( )
133
- . next ( )
134
- {
135
- // Valid UTF-8 character, cast the codepoint to u32 then T
136
- // (largest unicode codepoint is only 3 bytes, so this is safe)
137
- ( ( c as u32 ) . into ( ) , c. len_utf8 ( ) )
138
- } else {
139
- // Not a valid UTF-8 character, use the first byte
140
- ( bytes[ 0 ] . into ( ) , 1 )
141
- } ;
142
- // Emit a warning if there are additional characters
143
- if bytes. len ( ) > len {
144
- show_warning ! (
145
- "{}: character(s) following character constant have been ignored" ,
146
- String :: from_utf8_lossy( & bytes[ len..] )
147
- ) ;
148
- }
149
- return val;
123
+ // If this fails (this can only happens on Windows), then just
124
+ // return NotNumeric.
125
+ let s = match os_str_as_bytes ( os) {
126
+ Ok ( s) => s,
127
+ Err ( _) => return Err ( ExtendedParserError :: NotNumeric ) ,
128
+ } ;
129
+
130
+ let bytes = match s. split_first ( ) {
131
+ Some ( ( b'"' , bytes) ) | Some ( ( b'\'' , bytes) ) => bytes,
132
+ _ => {
133
+ // This really can't happen, the string we are given must start with '/".
134
+ debug_assert ! ( false ) ;
135
+ return Err ( ExtendedParserError :: NotNumeric ) ;
150
136
}
137
+ } ;
138
+
139
+ if bytes. is_empty ( ) {
140
+ return Err ( ExtendedParserError :: NotNumeric ) ;
151
141
}
142
+
143
+ let ( val, len) = if let Some ( c) = bytes
144
+ . utf8_chunks ( )
145
+ . next ( )
146
+ . expect ( "bytes should not be empty" )
147
+ . valid ( )
148
+ . chars ( )
149
+ . next ( )
150
+ {
151
+ // Valid UTF-8 character, cast the codepoint to u32 then T
152
+ // (largest unicode codepoint is only 3 bytes, so this is safe)
153
+ ( ( c as u32 ) . into ( ) , c. len_utf8 ( ) )
154
+ } else {
155
+ // Not a valid UTF-8 character, use the first byte
156
+ ( bytes[ 0 ] . into ( ) , 1 )
157
+ } ;
158
+ // Emit a warning if there are additional characters
159
+ if bytes. len ( ) > len {
160
+ return Err ( ExtendedParserError :: PartialMatch (
161
+ val,
162
+ String :: from_utf8_lossy ( & bytes[ len..] ) . to_string ( ) ,
163
+ ) ) ;
164
+ }
165
+
166
+ Ok ( val)
167
+ }
168
+
169
+ fn get_num < T > ( os : & OsStr ) -> T
170
+ where
171
+ T : ExtendedParser + From < u8 > + From < u32 > + Default ,
172
+ {
152
173
let s = os. to_string_lossy ( ) ;
153
- extract_value ( T :: extended_parse ( & s) , & s)
174
+ let first = s. as_bytes ( ) . first ( ) . copied ( ) ;
175
+
176
+ let quote_start = first == Some ( b'"' ) || first == Some ( b'\'' ) ;
177
+ let parsed = if quote_start {
178
+ // The string begins with a quote
179
+ Self :: parse_quote_start ( os)
180
+ } else {
181
+ T :: extended_parse ( & s)
182
+ } ;
183
+
184
+ // Get the best possible value, even if parsed was an error.
185
+ extract_value ( parsed, & s, quote_start)
154
186
}
155
187
156
188
fn get_at_relative_position ( & mut self , pos : NonZero < usize > ) -> Option < & ' a FormatArgument > {
@@ -172,7 +204,11 @@ impl<'a> FormatArguments<'a> {
172
204
}
173
205
}
174
206
175
- fn extract_value < T : Default > ( p : Result < T , ExtendedParserError < T > > , input : & str ) -> T {
207
+ fn extract_value < T : Default > (
208
+ p : Result < T , ExtendedParserError < T > > ,
209
+ input : & str ,
210
+ quote_start : bool ,
211
+ ) -> T {
176
212
match p {
177
213
Ok ( v) => v,
178
214
Err ( e) => {
@@ -192,8 +228,8 @@ fn extract_value<T: Default>(p: Result<T, ExtendedParserError<T>>, input: &str)
192
228
Default :: default ( )
193
229
}
194
230
ExtendedParserError :: PartialMatch ( v, rest) => {
195
- let bytes = input . as_encoded_bytes ( ) ;
196
- if !bytes . is_empty ( ) && ( bytes [ 0 ] == b'\'' || bytes [ 0 ] == b'"' ) {
231
+ if quote_start {
232
+ set_exit_code ( 0 ) ;
197
233
show_warning ! (
198
234
"{rest}: character(s) following character constant have been ignored"
199
235
) ;
0 commit comments