    {-# LANGUAGE CPP #-}
    #if __GLASGOW_HASKELL__ >= 800
    {-# LANGUAGE TemplateHaskellQuotes #-}
    #else
    {-# LANGUAGE TemplateHaskell #-}
    #endif

    module Text.Email.QuasiQuotation
        ( email
        ) where

    import qualified Data.ByteString.Char8 as BS8

    import Language.Haskell.TH.Quote (QuasiQuoter(..))

    import Text.Email.Validate (validate, localPart, domainPart, unsafeEmailAddress)

    -- | A QuasiQuoter for email addresses.
    --
    -- Use it like this (requires `QuasiQuotes` to be enabled):
    --
    -- >>> [email|someone@example.com|]
    -- "someone@example.com"
    email :: QuasiQuoter
    email :: QuasiQuoter
    email = QuasiQuoter
        { quoteExp :: String -> Q Exp
    quoteExp = (EmailAddress -> Q Exp) -> String -> Q Exp
    forall {a}. (EmailAddress -> a) -> String -> a
    quoteEmail EmailAddress -> Q Exp
    forall {m :: * -> *}. Quote m => EmailAddress -> m Exp
    emailToExp
        , quotePat :: String -> Q Pat
    quotePat = String -> String -> Q Pat
    forall a. HasCallStack => String -> a
    error String
    "email is not supported as a pattern"
        , quoteDec :: String -> Q [Dec]
    quoteDec = String -> String -> Q [Dec]
    forall a. HasCallStack => String -> a
    error String
    "email is not supported at top-level"
        , quoteType :: String -> Q Type
    quoteType = String -> String -> Q Type
    forall a. HasCallStack => String -> a
    error String
    "email is not supported as a type"
        }
        where

        quoteEmail :: (EmailAddress -> a) -> String -> a
    quoteEmail EmailAddress -> a
    p String
    s =
            case ByteString -> Either String EmailAddress
    validate (String -> ByteString
    BS8.pack String
    s) of
                Left String
    err -> String -> a
    forall a. HasCallStack => String -> a
    error (String
    "Invalid quasi-quoted email address: " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    err)
                Right EmailAddress
    e -> EmailAddress -> a
    p EmailAddress
    e

        emailToExp :: EmailAddress -> m Exp
    emailToExp EmailAddress
    e =
            let lp :: String
    lp = ByteString -> String
    BS8.unpack (EmailAddress -> ByteString
    localPart EmailAddress
    e) in
            let dp :: String
    dp = ByteString -> String
    BS8.unpack (EmailAddress -> ByteString
    domainPart EmailAddress
    e) in
            [| unsafeEmailAddress (BS8.pack lp) (BS8.pack dp) |]