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
= testGroup "DecimalMaxSO"
tests
[...
"paddedOK" $ Right 42 @=? parseWord8 "00042"
, testCase "paddedLarge" $
, testCase 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.