| 
 | 1 | +module Text.Domain.Validate  | 
 | 2 | +        ( isValid  | 
 | 3 | +        , validate  | 
 | 4 | +        , domainName  | 
 | 5 | +        , DomainName  | 
 | 6 | +        , toByteString  | 
 | 7 | +        )  | 
 | 8 | +where  | 
 | 9 | + | 
 | 10 | +import           Control.Applicative        ((<*))  | 
 | 11 | + | 
 | 12 | +import           Data.Attoparsec.ByteString (endOfInput, parseOnly)  | 
 | 13 | +import           Data.ByteString            (ByteString)  | 
 | 14 | + | 
 | 15 | +import           Data.Data                  (Data, Typeable)  | 
 | 16 | +import           GHC.Generics               (Generic)  | 
 | 17 | +import           Text.Email.Parser          (dottedAtoms)  | 
 | 18 | +import qualified Text.Read                  as Read  | 
 | 19 | + | 
 | 20 | + | 
 | 21 | +-- | Represents a domain name.  | 
 | 22 | +data DomainName = DomainName ByteString  | 
 | 23 | +    deriving (Eq, Ord, Data, Typeable, Generic)  | 
 | 24 | + | 
 | 25 | +-- | Smart constructor for a domain name  | 
 | 26 | +domainName :: ByteString -> Maybe DomainName  | 
 | 27 | +domainName = either (const Nothing) Just . validate  | 
 | 28 | + | 
 | 29 | +-- | Validates whether a particular string is a domain name  | 
 | 30 | +--   according to RFC5322.  | 
 | 31 | +isValid :: ByteString -> Bool  | 
 | 32 | +isValid = either (const False) (const True) . validate  | 
 | 33 | + | 
 | 34 | +-- | If you want to find out *why* a particular string is not  | 
 | 35 | +--   a domain name, use this.  | 
 | 36 | + | 
 | 37 | +validate :: ByteString -> Either String DomainName  | 
 | 38 | +validate = fmap DomainName . parseOnly (dottedAtoms <* endOfInput)  | 
 | 39 | + | 
 | 40 | +instance Show DomainName where  | 
 | 41 | +    show = show . toByteString  | 
 | 42 | + | 
 | 43 | +instance Read DomainName where  | 
 | 44 | +    readListPrec = Read.readListPrecDefault  | 
 | 45 | +    readPrec = Read.parens (do  | 
 | 46 | +        bs <- Read.readPrec  | 
 | 47 | +        case parseOnly (dottedAtoms <* endOfInput) bs of  | 
 | 48 | +            Left  _ -> Read.pfail  | 
 | 49 | +            Right a -> return $ DomainName a)  | 
 | 50 | + | 
 | 51 | +-- | Converts an email address back to a ByteString  | 
 | 52 | +toByteString :: DomainName -> ByteString  | 
 | 53 | +toByteString (DomainName d) = d  | 
0 commit comments