much better handling of bencode integers
authorRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Wed, 4 Feb 2015 09:32:16 +0000 (15:02 +0530)
committerRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Wed, 4 Feb 2015 09:32:16 +0000 (15:02 +0530)
src/Bencode.hs

index adc6d1ac1bc771541d4c81b89ef4d32dbdaee656..1fb2a31be5856b031a36cb503bdf7c9dd83d170d 100644 (file)
@@ -17,6 +17,9 @@ data BVal =
   | Bdict (M.Map BVal BVal)
   deriving (Ord, Eq)
 
+-- $setup
+-- >>> import Data.Either
+
 -- | parse strings
 --
 -- >>> parse bencStr "Bstr" (BC.pack "4:spam")
@@ -36,21 +39,33 @@ bencStr = do _ <- spaces
 --
 -- >>> parse bencInt "Bint" (BC.pack "i42e")
 -- Right 42
+-- >>> parse bencInt "Bint" (BC.pack "i123e")
+-- Right 123
 -- >>> parse bencInt "Bint" (BC.pack "i1e")
 -- Right 1
 -- >>> parse bencInt "Bint" (BC.pack "i0e")
 -- Right 0
 -- >>> parse bencInt "Bint" (BC.pack "i-1e")
 -- Right (-1)
+-- >>> isLeft $ parse bencInt "Bint" (BC.pack "i01e")
+-- True
+-- >>> isLeft $ parse bencInt "Bint" (BC.pack "i00e")
+-- True
+-- >>> isLeft $ parse bencInt "Bint" (BC.pack "i002e")
+-- True
 bencInt :: ParsecBS.Parser Integer
 bencInt = do _ <- spaces
              ds <- between (char 'i') (char 'e') numbers
              return (read ds)
                where numbers = do d' <- (char '-' <|> digit)
                                   ds' <- many digit
-                                  if d' == '0' && ds' /= []
-                                    then unexpected "numbers cannot be left-padded with zeros"
-                                    else return (d' : ds')
+                                  parseNumber d' ds'
+                     parseNumber '0' []  = return ['0']
+                     parseNumber '-' []  = unexpected "sign without any digits"
+                     parseNumber '0' ds'' = unexpected "numbers cannot be left-padded with zeros"
+                     parseNumber '-' (d'':ds'') | d'' == '0' = unexpected "numbers cannot be left-padded with zeros"
+                     parseNumber '-' ds'' = return ('-':ds'')
+                     parseNumber d'' ds'' = return (d'':ds'')
 
 bencParser :: ParsecBS.Parser BVal
 bencParser = Bstr <$> bencStr <|>