packages feed

serokell-util-0.1.1: src/Serokell/Util/Parse/Common.hs

{-# LANGUAGE MultiParamTypeClasses #-}

-- | Parsing common helpers

module Serokell.Util.Parse.Common
       ( Parser
       , countMinMax
       , limitedInt
       , byte
       , asciiAlphaNum
       ) where

import           Text.Parsec                        (Parsec, ParsecT, Stream, option,
                                                     satisfy)
import           Text.ParserCombinators.Parsec.Char (digit)

type Parser = Parsec String ()

isAsciiAlpha :: Char -> Bool
isAsciiAlpha c = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')

isAsciiNum :: Char -> Bool
isAsciiNum c = (c >= '0' && c <= '9')

isAsciiAlphaNum :: Char -> Bool
isAsciiAlphaNum c = isAsciiAlpha c || isAsciiNum c

asciiAlphaNum :: Parser Char
asciiAlphaNum = satisfy isAsciiAlphaNum

countMinMax :: (Stream s m t) => Int -> Int -> ParsecT s u m a -> ParsecT s u m [a]
countMinMax m x p
    | m > 0 = do
        f <- p
        end <- countMinMax (m - 1) (x - 1) p
        return $ f : end
    | x <= 0 = return []
    | otherwise = option [] $ do
        f <- p
        end <- countMinMax 0 (x - 1) p
        return $ f : end

limitedInt :: Int -> String -> Parser Int
limitedInt x e = do
    b <- read <$> countMinMax 1 (intDigits x) digit
    if b > x
        then fail e
        else return b
  where
    intDigits = length . show

byte :: Parser Word
byte = fromIntegral <$> limitedInt 255 "Value to large"