haskell - parsing n hex digits using attoparsec -
okay need parse n digits of hex , having problem cant stop standard attoparsec hex parser hexadecimal
.
my first idea this:
nhex n = take n *> hexadecimal
doesnt work because takes off 4 digits parses rest of string xd
next idea works this:
hex :: (num a, eq a) => int -> parser hex n = fst . head . readhex <$> count n (satisfy ishexdigit)
but problem code in attoparsec library warns against returning lists of chars speed concerns , hex parser base of whole program
next idea try better speed this:
parsefragments :: (bits a, integral a) => int -> parser parsefragments n = fourchars <- b.take n let hexdigits = parseonly hexadecimal fourchars case hexdigits of left err -> fail err right x -> return x
but feels terrible hack using parseonly. there fast way more idiomatic?
data.attoparsec.bytestring.char8.hexadecimal
implemented as:
hexadecimal :: (integral a, bits a) => parser hexadecimal = b8.foldl' step 0 `fmap` i.takewhile1 ishexdigit ishexdigit w = (w >= 48 && w <= 57) || (w >= 97 && w <= 102) || (w >= 65 && w <= 70) step w | w >= 48 && w <= 57 = (a `shiftl` 4) .|. fromintegral (w - 48) | w >= 97 = (a `shiftl` 4) .|. fromintegral (w - 87) | otherwise = (a `shiftl` 4) .|. fromintegral (w - 55)
you can use pretty same, except need insepct result of take
, of characters might not valid hexadecimal characters. use (maybe -> word8 -> maybe a)
put both in same function, simplicity, i've used functions above:
fixedhexadecimal :: (integral a, bits a) => int -> parser fixedhexadecimal n = bytes <- a.take n if b8.all ishexdigit bytes b8.foldl' step 0 bytes else fail "fixedhexadecimal" ishexdigit = -- see above step = -- see above