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