
module Text.Domain.Parser.Polymorphic (
    domainParser,
    isAsciiAlphaNum
    ) where

import Text.Parser.Combinators
import Text.Parser.Char
import Data.Char (isAscii, isAlpha, isDigit)
import Data.List (intercalate)

domainParser :: (Monad m, CharParsing m) => m String
domainParser = do
    labels <- label `sepBy1` (char '.')
    _ <- optional (char '.')
    let domain = intercalate "." labels
    -- domain name must be no greater than 253 chars
    if length domain <= 253
        then return domain
        else fail "domain length too long."

label :: (Monad m, CharParsing m) => m String
label = do
    l <- satisfy isAsciiAlphaNum
    abelString <- many $ satisfy isAsciiAlphaNumHyphen
    let labelString = l : abelString
    -- label must be no greater than 63 chars and cannot end with '-'
    if length labelString <= 63 && last labelString /= '-'
        then return labelString
        else fail "label too long."

isAsciiAlpha :: Char -> Bool
isAsciiAlpha x = isAscii x && isAlpha x

isAsciiAlphaNum :: Char -> Bool
isAsciiAlphaNum x = isAsciiAlpha x || isDigit x

isAsciiAlphaNumHyphen :: Char -> Bool
isAsciiAlphaNumHyphen x = isAsciiAlphaNum x || x == '-'
