Parsing Bounded Integers (Part 2)
I realized that I missed a significant issue with the DecimalMaxSO
and DecimalMaxFixed
implementations in the Parsing Bounded
Integers blog entry! These parsers limit the number of characters
that are consumed by counting digits, where the maximum number of digits
is the number of digits of the maximum bound. They do not take
leading zeros into account, however. In some cases, this leads to
failure in cases where the decimal parser succeeds, and the
failures have potentially puzzling error messages.
The new tests are as follows:
tests :: TestTree
tests = testGroup "DecimalMaxSO"
    [
    ...
    , testCase "paddedOK" $ Right 42 @=? parseWord8 "00042"
    , testCase "paddedLarge" $
        Left "Failed reading: decimalMax: parsed decimal exeeded 255"
          @=? parseWord8 "01000"
    ...
    ]Both the DecimalMaxSO and DecimalMaxFixed implementations fail these tests with errors like the following:
paddedOK:      FAIL
  test/DecimalMaxSO/Test.hs:44:
  expected: Right 42
   but got: Left "endOfInput"
  Use -p '/DecimalMaxSO.paddedOK/' to rerun this test only.
paddedLarge:   FAIL
  test/DecimalMaxSO/Test.hs:46:
  expected: Left "Failed reading: decimalMax: parsed decimal exeeded 255"
   but got: Left "endOfInput"
  Use -p '/DecimalMaxSO.paddedLarge/' to rerun this test only.In the paddedOK test, the scan function
consumes four digits, returning the ByteString value
0004 and leaving the 2 unconsumed. (Notice
that numDigs is 3, but four digits are consumed because the
state starts at zero. This is essential because that extra digit is
sometimes required to determine that there is an overflow.) The
decimalMax parser succeeds, returning 4, and then the
endOfInput function fails because 2
remains.
In the paddedLarge test, the scan function
consumes four digits, returning the ByteString value
0100 and leaving the final 0 unconsumed. The
decimalMax parser succeeds, returning 100, and then the
endOfInput function fails because 0
remains.