1 //! Validate buffers and other information.
2 
3 use crate::util::*;
4 use super::traits::*;
5 
6 // HELPERS
7 
8 // Determine if the integer component is empty.
9 perftools_inline!{
10 fn is_integer_empty<'a, Data>(data: &Data)
11     -> bool
12     where Data: FastDataInterface<'a>
13 {
14     data.integer_iter().next().is_none()
15 }}
16 
17 // Determine if the fraction component is empty.
18 perftools_inline!{
19 fn is_fraction_empty<'a, Data>(data: &Data)
20     -> bool
21     where Data: FastDataInterface<'a>
22 {
23     data.fraction_iter().next().is_none()
24 }}
25 
26 // Determine if the fraction component exists.
27 perftools_inline!{
28 #[cfg(feature = "format")]
29 fn has_fraction<'a, Data>(data: &Data)
30     -> bool
31     where Data: FastDataInterface<'a>
32 {
33     data.fraction().is_some()
34 }}
35 
36 // Determine if the exponent component exists.
37 perftools_inline!{
38 fn has_exponent<'a, Data>(data: &Data)
39     -> bool
40     where Data: FastDataInterface<'a>
41 {
42     data.exponent().is_some()
43 }}
44 
45 // Unwrap option to get the pointer.
46 perftools_inline!{
47 fn option_as_ptr(option: Option<&[u8]>) -> *const u8
48 {
49     option.unwrap().as_ptr()
50 }}
51 
52 // MANTISSA
53 
54 // Validate the extracted integer has no leading zeros.
55 perftools_inline!{
56 #[cfg(feature = "format")]
57 pub(super) fn validate_no_leading_zeros<'a, Data>(data: &Data)
58     -> ParseResult<()>
59     where Data: FastDataInterface<'a>
60 {
61     // Check if the next character is a sign symbol.
62     let mut iter = data.integer_iter();
63     match iter.next() {
64         Some(&b'0')     => (),
65         _               => return Ok(())
66     };
67 
68     // Only here if we have a leading 0 symbol.
69     match iter.next() {
70         Some(_) => Err((ErrorCode::InvalidLeadingZeros, data.integer().as_ptr())),
71         None    => Ok(())
72     }
73 }}
74 
75 // Validate the extracted mantissa float components.
76 //      1. Validate non-empty significant digits (integer or fraction).
77 perftools_inline!{
78 pub(super) fn validate_permissive_mantissa<'a, Data>(data: &Data)
79     -> ParseResult<()>
80     where Data: FastDataInterface<'a>
81 {
82     let integer_empty = is_integer_empty(data);
83     let fraction_empty = is_fraction_empty(data);
84     if integer_empty && fraction_empty {
85         // Invalid floating-point number, no integer or fraction components.
86         Err((ErrorCode::EmptyMantissa, data.integer().as_ptr()))
87     } else {
88         Ok(())
89     }
90 }}
91 
92 // Validate the extracted mantissa float components.
93 //      1. Validate integer component is non-empty.
94 perftools_inline!{
95 #[cfg(feature = "format")]
96 pub(super) fn validate_required_integer<'a, Data>(data: &Data)
97     -> ParseResult<()>
98     where Data: FastDataInterface<'a>
99 {
100     if is_integer_empty(data) {
101         // Invalid floating-point number, no integer component.
102         Err((ErrorCode::EmptyInteger, data.integer().as_ptr()))
103     } else {
104         Ok(())
105     }
106 }}
107 
108 // Validate the extracted mantissa float components.
109 //      1. Validate fraction component is non-empty if present.
110 perftools_inline!{
111 #[cfg(feature = "format")]
112 pub(super) fn validate_required_fraction<'a, Data>(data: &Data)
113     -> ParseResult<()>
114     where Data: FastDataInterface<'a>
115 {
116     if has_fraction(data) && is_fraction_empty(data) {
117         // Invalid floating-point number, no fraction component.
118         Err((ErrorCode::EmptyFraction, option_as_ptr(data.fraction())))
119     } else {
120         Ok(())
121     }
122 }}
123 
124 // Validate the extracted mantissa float components.
125 //      1. Validate integer component is non-empty.
126 //      2. Validate fraction component is non-empty if present.
127 perftools_inline!{
128 #[cfg(feature = "format")]
129 pub(super) fn validate_required_digits<'a, Data>(data: &Data)
130     -> ParseResult<()>
131     where Data: FastDataInterface<'a>
132 {
133     if is_integer_empty(data) {
134         // Invalid floating-point number, no integer component.
135         Err((ErrorCode::EmptyInteger, data.integer().as_ptr()))
136     } else if has_fraction(data) && is_fraction_empty(data) {
137         // Invalid floating-point number, no fraction component.
138         Err((ErrorCode::EmptyFraction, option_as_ptr(data.fraction())))
139     } else {
140         Ok(())
141     }
142 }}
143 
144 // Validate mantissa depending on float format.
145 perftools_inline!{
146 #[cfg(feature = "format")]
147 pub(super) fn validate_mantissa<'a, Data>(data: &Data, format: NumberFormat)
148     -> ParseResult<()>
149     where Data: FastDataInterface<'a>
150 {
151     // Check no leading zeros.
152     if format.no_float_leading_zeros() {
153         validate_no_leading_zeros(data)?;
154     }
155 
156     // Check required digits.
157     let required_integer = format.required_integer_digits();
158     let required_fraction = format.required_fraction_digits();
159     match (required_integer, required_fraction) {
160         (true, true)    => validate_required_digits(data),
161         (false, true)   => validate_required_fraction(data),
162         (true, false)   => validate_required_integer(data),
163         (false, false)  => validate_permissive_mantissa(data)
164     }
165 }}
166 
167 // EXPONENT
168 
169 // Validate the required exponent component.
170 //      1). If the exponent has been defined, ensure at least 1 digit follows it.
171 perftools_inline!{
172 pub(super) fn validate_required_exponent<'a, Data>(data: &Data)
173     -> ParseResult<()>
174     where Data: FastDataInterface<'a>
175 {
176     // If we don't have an exponent stored, we're fine.
177     if !has_exponent(data) {
178         return Ok(())
179     }
180 
181     // Check if the next character is a sign symbol.
182     let mut iter = data.exponent_iter();
183     match iter.next() {
184         Some(&b'+') | Some(&b'-')   => (),
185         Some(_)                     => return Ok(()),
186         None                        => return Err((ErrorCode::EmptyExponent, option_as_ptr(data.exponent())))
187     };
188 
189     // Only here if we have a sign symbol.
190     match iter.next() {
191         Some(_) => Ok(()),
192         None    => Err((ErrorCode::EmptyExponent, option_as_ptr(data.exponent())))
193     }
194 }}
195 
196 // Validate optional exponent component.
197 //      A no-op, since the data is optional.
198 perftools_inline!{
199 #[cfg(feature = "format")]
200 pub(super) fn validate_optional_exponent<'a, Data>(_: &Data)
201     -> ParseResult<()>
202     where Data: FastDataInterface<'a>
203 {
204     Ok(())
205 }}
206 
207 // Validate invalid exponent component.
208 perftools_inline!{
209 #[cfg(feature = "format")]
210 pub(super) fn validate_invalid_exponent<'a, Data>(data: &Data)
211     -> ParseResult<()>
212     where Data: FastDataInterface<'a>
213 {
214     match has_exponent(data) {
215         true  => return Err((ErrorCode::InvalidExponent, option_as_ptr(data.exponent()))),
216         false => Ok(())
217     }
218 }}
219 
220 // Validate exponent depending on float format.
221 perftools_inline!{
222 #[cfg(feature = "format")]
223 pub(super) fn validate_exponent<'a, Data>(data: &Data, format: NumberFormat)
224     -> ParseResult<()>
225     where Data: FastDataInterface<'a>
226 {
227     let required = format.required_exponent_digits();
228     let invalid = format.no_exponent_notation();
229     match (required, invalid) {
230         (true, _)       => validate_required_exponent(data),
231         (_, true)       => validate_invalid_exponent(data),
232         (false, false)  => validate_optional_exponent(data)
233     }
234 }}
235 
236 // EXPONENT SIGN
237 
238 // Validate optional exponent sign.
239 //      A no-op, since the data is optional.
240 perftools_inline!{
241 pub(super) fn validate_optional_exponent_sign<'a, Data>(_: &Data)
242     -> ParseResult<()>
243     where Data: FastDataInterface<'a>
244 {
245     Ok(())
246 }}
247 
248 // Validate a required exponent sign.
249 perftools_inline!{
250 #[cfg(feature = "format")]
251 pub(super) fn validate_required_exponent_sign<'a, Data>(data: &Data)
252     -> ParseResult<()>
253     where Data: FastDataInterface<'a>
254 {
255     // Check if the next character is a sign symbol.
256     let mut iter = data.exponent_iter();
257     match iter.next() {
258         Some(&b'+') | Some(&b'-')   => Ok(()),
259         _ if has_exponent(data)     => Err((ErrorCode::MissingExponentSign, option_as_ptr(data.exponent()))),
260         _                           => Ok(())
261     }
262 }}
263 
264 // Validate a required exponent sign.
265 perftools_inline!{
266 #[cfg(feature = "format")]
267 pub(super) fn validate_no_positive_exponent_sign<'a, Data>(data: &Data)
268     -> ParseResult<()>
269     where Data: FastDataInterface<'a>
270 {
271     // Check if the next character is a sign symbol.
272     let mut iter = data.exponent_iter();
273     match iter.next() {
274         Some(&b'+') => Err((ErrorCode::InvalidPositiveExponentSign, option_as_ptr(data.exponent()))),
275         _           => Ok(())
276     }
277 }}
278 
279 // Validate exponent sign depending on float format.
280 perftools_inline!{
281 #[cfg(feature = "format")]
282 pub(super) fn validate_exponent_sign<'a, Data>(data: &Data, format: NumberFormat)
283     -> ParseResult<()>
284     where Data: FastDataInterface<'a>
285 {
286     let required = format.required_exponent_sign();
287     let no_positive = format.no_positive_exponent_sign();
288     match (required, no_positive) {
289         (true, _)       => validate_required_exponent_sign(data),
290         (_, true)       => validate_no_positive_exponent_sign(data),
291         (false, false)  => validate_optional_exponent_sign(data)
292     }
293 }}
294 
295 // EXPONENT FRACTION
296 
297 // Validate an exponent may occur with or without a fraction.
298 perftools_inline!{
299 pub(super) fn validate_exponent_optional_fraction<'a, Data>(_: &Data)
300     -> ParseResult<()>
301     where Data: FastDataInterface<'a>
302 {
303     Ok(())
304 }}
305 
306 // Validate an exponent requires a fraction component.
307 perftools_inline!{
308 #[cfg(feature = "format")]
309 pub(super) fn validate_exponent_required_fraction<'a, Data>(data: &Data)
310     -> ParseResult<()>
311     where Data: FastDataInterface<'a>
312 {
313     match has_exponent(data) && !has_fraction(data) {
314         true  => Err((ErrorCode::ExponentWithoutFraction, option_as_ptr(data.exponent()))),
315         false => Ok(())
316     }
317 }}
318 
319 // Validate exponent fraction depending on float format.
320 perftools_inline!{
321 #[cfg(feature = "format")]
322 pub(super) fn validate_exponent_fraction<'a, Data>(data: &Data, format: NumberFormat)
323     -> ParseResult<()>
324     where Data: FastDataInterface<'a>
325 {
326     match format.no_exponent_without_fraction() {
327         true  => validate_exponent_required_fraction(data),
328         false => validate_exponent_optional_fraction(data)
329     }
330 }}
331 
332 // TESTS
333 // -----
334 
335 #[cfg(test)]
336 mod tests {
337     use super::*;
338     use super::super::standard::*;
339 
340     #[test]
341     #[cfg(feature = "format")]
validate_no_leading_zeros_test()342     fn validate_no_leading_zeros_test() {
343         type Data<'a> = StandardFastDataInterface<'a>;
344         let data: Data = (b!("01"), Some(b!("23450")), None, 0).into();
345         assert!(validate_no_leading_zeros(&data).is_err());
346 
347         let data: Data = (b!("1"), Some(b!("23450")), None, 0).into();
348         assert!(validate_no_leading_zeros(&data).is_ok());
349 
350         let data: Data = (b!("0"), Some(b!("23450")), None, 0).into();
351         assert!(validate_no_leading_zeros(&data).is_ok());
352 
353         let data: Data = (b!(""), Some(b!("23450")), None, 0).into();
354         assert!(validate_no_leading_zeros(&data).is_ok());
355     }
356 
357     #[test]
validate_permissive_mantissa_test()358     fn validate_permissive_mantissa_test() {
359         type Data<'a> = StandardFastDataInterface<'a>;
360         let data: Data = (b!("01"), Some(b!("23450")), None, 0).into();
361         assert!(validate_permissive_mantissa(&data).is_ok());
362 
363         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
364         assert!(validate_permissive_mantissa(&data).is_ok());
365 
366         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
367         assert!(validate_permissive_mantissa(&data).is_ok());
368 
369         let data: Data = (b!(""), Some(b!("")), Some(b!("+")), 0).into();
370         assert!(validate_permissive_mantissa(&data).is_err());
371     }
372 
373     #[test]
374     #[cfg(feature = "format")]
validate_required_integer_test()375     fn validate_required_integer_test() {
376         type Data<'a> = StandardFastDataInterface<'a>;
377         let data: Data = (b!("01"), Some(b!("23450")), None, 0).into();
378         assert!(validate_required_integer(&data).is_ok());
379 
380         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
381         assert!(validate_required_integer(&data).is_ok());
382 
383         let data: Data = (b!(""), Some(b!("0")), Some(b!("")), 0).into();
384         assert!(validate_required_integer(&data).is_err());
385 
386         let data: Data = (b!(""), Some(b!("")), Some(b!("")), 0).into();
387         assert!(validate_required_integer(&data).is_err());
388     }
389 
390     #[test]
391     #[cfg(feature = "format")]
validate_required_fraction_test()392     fn validate_required_fraction_test() {
393         type Data<'a> = StandardFastDataInterface<'a>;
394         let data: Data = (b!("01"), Some(b!("23450")), None, 0).into();
395         assert!(validate_required_fraction(&data).is_ok());
396 
397         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
398         assert!(validate_required_fraction(&data).is_err());
399 
400         let data: Data = (b!(""), Some(b!("0")), Some(b!("")), 0).into();
401         assert!(validate_required_fraction(&data).is_ok());
402 
403         let data: Data = (b!(""), Some(b!("")), Some(b!("")), 0).into();
404         assert!(validate_required_fraction(&data).is_err());
405     }
406 
407     #[test]
408     #[cfg(feature = "format")]
validate_required_digits_test()409     fn validate_required_digits_test() {
410         type Data<'a> = StandardFastDataInterface<'a>;
411         let data: Data = (b!("01"), Some(b!("23450")), None, 0).into();
412         assert!(validate_required_digits(&data).is_ok());
413 
414         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
415         assert!(validate_required_digits(&data).is_err());
416 
417         let data: Data = (b!(""), Some(b!("0")), Some(b!("")), 0).into();
418         assert!(validate_required_digits(&data).is_err());
419 
420         let data: Data = (b!(""), Some(b!("")), Some(b!("")), 0).into();
421         assert!(validate_required_digits(&data).is_err());
422     }
423 
424     #[test]
validate_required_exponent_test()425     fn validate_required_exponent_test() {
426         type Data<'a> = StandardFastDataInterface<'a>;
427         let data: Data = (b!("01"), Some(b!("23450")), None, 0).into();
428         assert!(validate_required_exponent(&data).is_ok());
429 
430         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
431         assert!(validate_required_exponent(&data).is_err());
432 
433         let data: Data = (b!(""), Some(b!("")), Some(b!("+")), 0).into();
434         assert!(validate_required_exponent(&data).is_err());
435 
436         let data: Data = (b!(""), Some(b!("")), Some(b!("2")), 0).into();
437         assert!(validate_required_exponent(&data).is_ok());
438 
439         let data: Data = (b!(""), Some(b!("")), Some(b!("+2")), 0).into();
440         assert!(validate_required_exponent(&data).is_ok());
441     }
442 
443     #[test]
444     #[cfg(feature = "format")]
validate_optional_exponent_test()445     fn validate_optional_exponent_test() {
446         type Data<'a> = StandardFastDataInterface<'a>;
447         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
448         assert!(validate_optional_exponent(&data).is_ok());
449 
450         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
451         assert!(validate_optional_exponent(&data).is_ok());
452 
453         let data: Data = (b!("0"), Some(b!("")), Some(b!("+")), 0).into();
454         assert!(validate_optional_exponent(&data).is_ok());
455 
456         let data: Data = (b!("0"), Some(b!("")), Some(b!("2")), 0).into();
457         assert!(validate_optional_exponent(&data).is_ok());
458 
459         let data: Data = (b!("0"), Some(b!("")), Some(b!("+2")), 0).into();
460         assert!(validate_optional_exponent(&data).is_ok());
461     }
462 
463     #[test]
464     #[cfg(feature = "format")]
validate_invalid_exponent_test()465     fn validate_invalid_exponent_test() {
466         type Data<'a> = StandardFastDataInterface<'a>;
467         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
468         assert!(validate_invalid_exponent(&data).is_ok());
469 
470         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
471         assert!(validate_invalid_exponent(&data).is_err());
472 
473         let data: Data = (b!("0"), Some(b!("")), Some(b!("+")), 0).into();
474         assert!(validate_invalid_exponent(&data).is_err());
475 
476         let data: Data = (b!("0"), Some(b!("")), Some(b!("2")), 0).into();
477         assert!(validate_invalid_exponent(&data).is_err());
478 
479         let data: Data = (b!("0"), Some(b!("")), Some(b!("+2")), 0).into();
480         assert!(validate_invalid_exponent(&data).is_err());
481     }
482 
483     #[test]
validate_optional_exponent_sign_test()484     fn validate_optional_exponent_sign_test() {
485         type Data<'a> = StandardFastDataInterface<'a>;
486         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
487         assert!(validate_optional_exponent_sign(&data).is_ok());
488 
489         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
490         assert!(validate_optional_exponent_sign(&data).is_ok());
491 
492         let data: Data = (b!("0"), Some(b!("")), Some(b!("+")), 0).into();
493         assert!(validate_optional_exponent_sign(&data).is_ok());
494 
495         let data: Data = (b!("0"), Some(b!("")), Some(b!("2")), 0).into();
496         assert!(validate_optional_exponent_sign(&data).is_ok());
497 
498         let data: Data = (b!("0"), Some(b!("")), Some(b!("+2")), 0).into();
499         assert!(validate_optional_exponent_sign(&data).is_ok());
500     }
501 
502     #[test]
503     #[cfg(feature = "format")]
validate_required_exponent_sign_test()504     fn validate_required_exponent_sign_test() {
505         type Data<'a> = StandardFastDataInterface<'a>;
506         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
507         assert!(validate_required_exponent_sign(&data).is_ok());
508 
509         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
510         assert!(validate_required_exponent_sign(&data).is_err());
511 
512         let data: Data = (b!("0"), Some(b!("")), Some(b!("+")), 0).into();
513         assert!(validate_required_exponent_sign(&data).is_ok());
514 
515         let data: Data = (b!("0"), Some(b!("")), Some(b!("2")), 0).into();
516         assert!(validate_required_exponent_sign(&data).is_err());
517 
518         let data: Data = (b!("0"), Some(b!("")), Some(b!("+2")), 0).into();
519         assert!(validate_required_exponent_sign(&data).is_ok());
520     }
521 
522     #[test]
523     #[cfg(feature = "format")]
validate_no_positive_exponent_sign_test()524     fn validate_no_positive_exponent_sign_test() {
525         type Data<'a> = StandardFastDataInterface<'a>;
526         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
527         assert!(validate_no_positive_exponent_sign(&data).is_ok());
528 
529         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
530         assert!(validate_no_positive_exponent_sign(&data).is_ok());
531 
532         let data: Data = (b!("0"), Some(b!("")), Some(b!("+")), 0).into();
533         assert!(validate_no_positive_exponent_sign(&data).is_err());
534 
535         let data: Data = (b!("0"), Some(b!("")), Some(b!("2")), 0).into();
536         assert!(validate_no_positive_exponent_sign(&data).is_ok());
537 
538         let data: Data = (b!("0"), Some(b!("")), Some(b!("+2")), 0).into();
539         assert!(validate_no_positive_exponent_sign(&data).is_err());
540 
541         let data: Data = (b!("0"), Some(b!("")), Some(b!("-2")), 0).into();
542         assert!(validate_no_positive_exponent_sign(&data).is_ok());
543     }
544 
545     #[test]
validate_exponent_optional_fraction_test()546     fn validate_exponent_optional_fraction_test() {
547         type Data<'a> = StandardFastDataInterface<'a>;
548         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
549         assert!(validate_exponent_optional_fraction(&data).is_ok());
550 
551         let data: Data = (b!(""), Some(b!("0")), None, 0).into();
552         assert!(validate_exponent_optional_fraction(&data).is_ok());
553 
554         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
555         assert!(validate_exponent_optional_fraction(&data).is_ok());
556 
557         let data: Data = (b!(""), Some(b!("0")), Some(b!("+")), 0).into();
558         assert!(validate_exponent_optional_fraction(&data).is_ok());
559     }
560 
561     #[test]
562     #[cfg(feature = "format")]
validate_exponent_required_fraction_test()563     fn validate_exponent_required_fraction_test() {
564         type Data<'a> = StandardFastDataInterface<'a>;
565         let data: Data = (b!("0"), Some(b!("")), None, 0).into();
566         assert!(validate_exponent_required_fraction(&data).is_ok());
567 
568         let data: Data = (b!("0"), Some(b!("")), Some(b!("")), 0).into();
569         assert!(validate_exponent_required_fraction(&data).is_ok());
570 
571         let data: Data = (b!("0"), None, Some(b!("")), 0).into();
572         assert!(validate_exponent_required_fraction(&data).is_err());
573 
574         let data: Data = (b!(""), Some(b!("0")), Some(b!("+")), 0).into();
575         assert!(validate_exponent_required_fraction(&data).is_ok());
576     }
577 }
578