module Data.URI.Auth.Host where
import Prelude hiding (Either (..))
import Data.Vector (Vector)
import qualified Data.Vector as V
import Data.Text (Text)
import qualified Data.Text as T
import Data.Attoparsec.Text (Parser, char, sepBy1, takeWhile1)
import Data.Attoparsec.IP (ipv4, ipv6)
import Control.Applicative ((<|>))
import Net.Types (IPv4, IPv6)
import qualified Net.IPv4 as IPv4
import qualified Net.IPv6 as IPv6
import Data.Data (Typeable)
import GHC.Generics (Generic)
data URIAuthHost
= IPv4 !IPv4
| IPv6 !IPv6
| Localhost
|
Host
{ uriAuthHostName :: !(Vector Text)
, uriAuthHostSuffix :: !Text
} deriving (Eq, Typeable, Generic)
printURIAuthHost :: URIAuthHost -> Text
printURIAuthHost x = case x of
IPv4 l4 -> IPv4.encode l4
IPv6 r6 -> IPv6.encode r6
Localhost -> "localhost"
Host ns c -> T.intercalate "." (V.toList (ns `V.snoc` c))
parseURIAuthHost :: Parser URIAuthHost
parseURIAuthHost =
(IPv4 <$> ipv4)
<|> (IPv6 <$> ipv6)
<|> parseHost
where
parseHost :: Parser URIAuthHost
parseHost = do
xss@(x:xs) <- takeWhile1 (\c -> c `notElem` ['.',':','/','?']) `sepBy1` char '.'
if null xs
then if x == "localhost"
then pure Localhost
else fail $ "Only one term parsed: " ++ show xss
else let xss' :: Vector Text
xss' = V.fromList xss
unsnoc :: Vector a -> (Vector a, a)
unsnoc x' =
let (fs,l) = V.splitAt (V.length x' 1) x'
in (fs, l V.! 0)
(ns,c) = unsnoc xss'
in pure (Host ns c)