-- |
-- Module      : Net.DNSBase.Internal.Text
-- Description : TBD
-- Copyright   : (c) Viktor Dukhovni, 2026
-- License     : BSD-3-Clause
-- Maintainer  : ietf-dane@dukhovni.org
-- Stability   : unstable
module Net.DNSBase.Internal.Text
    ( DnsText(..)
    , DnsUtf8Text(..)
    , dnsTextCmp
    , presentCharString
    , presentDomainLabel
    , presentHostLabel
    , presentCSVList
    ) where

import qualified Data.ByteString.Builder as B
import qualified Data.ByteString.Builder.Internal as B
import qualified Data.ByteString.Builder.Prim as P
import qualified Data.ByteString.Builder.Prim.Internal as P
import qualified Data.ByteString.Short as SB
import qualified Data.Text as T
import qualified Data.Text.Array as TA
import qualified Data.Text.Internal as T
import Data.ByteString.Builder.Prim ((>$<), (>*<))

import Net.DNSBase.Internal.Present
import Net.DNSBase.Internal.Util

newtype DnsText = DnsText SB.ShortByteString -- ^ Character string
    deriving (DnsText -> DnsText -> Bool
(DnsText -> DnsText -> Bool)
-> (DnsText -> DnsText -> Bool) -> Eq DnsText
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DnsText -> DnsText -> Bool
== :: DnsText -> DnsText -> Bool
$c/= :: DnsText -> DnsText -> Bool
/= :: DnsText -> DnsText -> Bool
Eq, Int -> DnsText -> ShowS
[DnsText] -> ShowS
DnsText -> String
(Int -> DnsText -> ShowS)
-> (DnsText -> String) -> ([DnsText] -> ShowS) -> Show DnsText
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DnsText -> ShowS
showsPrec :: Int -> DnsText -> ShowS
$cshow :: DnsText -> String
show :: DnsText -> String
$cshowList :: [DnsText] -> ShowS
showList :: [DnsText] -> ShowS
Show)

-- | Canonical wire-form comparison of DNS character strings.
instance Ord DnsText where
    (DnsText ShortByteString
a) compare :: DnsText -> DnsText -> Ordering
`compare` (DnsText ShortByteString
b) = ShortByteString -> Int
SB.length ShortByteString
a Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` ShortByteString -> Int
SB.length ShortByteString
b
                                     Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<>           ShortByteString
a ShortByteString -> ShortByteString -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`           ShortByteString
b

instance Presentable DnsText where
    present :: DnsText -> Builder -> Builder
present = ShortByteString -> Builder -> Builder
presentCharString (ShortByteString -> Builder -> Builder)
-> (DnsText -> ShortByteString) -> DnsText -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DnsText -> ShortByteString
forall a b. Coercible a b => a -> b
coerce

-- | Compare wire-form /character-strings/, by length first.
dnsTextCmp :: Coercible a ShortByteString => a -> a -> Ordering
dnsTextCmp :: forall a. Coercible a ShortByteString => a -> a -> Ordering
dnsTextCmp a
x a
y = ShortByteString -> DnsText
DnsText (a -> ShortByteString
forall a b. Coercible a b => a -> b
coerce a
x) DnsText -> DnsText -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` ShortByteString -> DnsText
DnsText (a -> ShortByteString
forall a b. Coercible a b => a -> b
coerce a
y)

-- | Present a dns /character-string/ with the given continuation.
-- The result is enclosed in double-quotes.
--
presentCharString :: SB.ShortByteString  -- ^ The bytes to encode.
                  -> Builder             -- ^ Continuation
                  -> B.Builder
{-# INLINE presentCharString #-}
presentCharString :: ShortByteString -> Builder -> Builder
presentCharString (ShortByteString -> ByteString
SB.fromShort -> ByteString
bytes) Builder
k =
    Word8 -> Builder
B.word8 Word8
W_dquote Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> BoundedPrim Word8 -> ByteString -> Builder
P.primMapByteStringBounded BoundedPrim Word8
bp ByteString
bytes Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
B.word8 Word8
W_dquote Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
k
  where
    isprint :: Word8 -> Bool
isprint = \Word8
w -> Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
W_space Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
W_delete
    bp :: BoundedPrim Word8
bp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
isprint BoundedPrim Word8
sp BoundedPrim Word8
decEscBP
    sp :: BoundedPrim Word8
sp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
special BoundedPrim Word8
bsEscBP BoundedPrim Word8
charBP
    special :: Word8 -> Bool
special = \ case
        Word8
W_dquote -> Bool
True
        Word8
W_bslash -> Bool
True
        Word8
_        -> Bool
False

-- | Present a 'Net.DNSBase.Domain.Domain' label with the given continuation.
--
presentDomainLabel :: Word8       -- ^ Label separator, typically 0x2e ('.').
                   -> ByteString  -- ^ The bytes to encode.
                   -> Builder     -- ^ Continuation
                   -> B.Builder
{-# INLINE presentDomainLabel #-}
presentDomainLabel :: Word8 -> ByteString -> Builder -> Builder
presentDomainLabel Word8
sep ByteString
bytes Builder
k =
    BoundedPrim Word8 -> ByteString -> Builder
P.primMapByteStringBounded BoundedPrim Word8
bp ByteString
bytes Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
k
  where
    isgraph :: Word8 -> Bool
isgraph = \Word8
w -> Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
W_space Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
W_delete
    bp :: BoundedPrim Word8
bp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
isgraph BoundedPrim Word8
sp BoundedPrim Word8
decEscBP
    sp :: BoundedPrim Word8
sp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
special BoundedPrim Word8
bsEscBP BoundedPrim Word8
charBP
      where
        special :: Word8 -> Bool
special = \ case
            Word8
W_dquote -> Bool
True
            Word8
W_bslash -> Bool
True
            Word8
W_dollar -> Bool
True
            Word8
W_open   -> Bool
True
            Word8
W_close  -> Bool
True
            Word8
W_semi   -> Bool
True
            Word8
W_at     -> Bool
True
            Word8
w        -> Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
sep

-- | Present a 'Net.DNSBase.Domain.Host' label folded to lower case, with the given continuation.
--
presentHostLabel :: Word8       -- ^ Label separator, typically 0x2e ('.').
                 -> ByteString  -- ^ The bytes to encode.
                 -> Builder     -- ^ Continuation
                 -> B.Builder
{-# INLINE presentHostLabel #-}
presentHostLabel :: Word8 -> ByteString -> Builder -> Builder
presentHostLabel Word8
sep ByteString
bytes Builder
k =
    BoundedPrim Word8 -> ByteString -> Builder
P.primMapByteStringBounded BoundedPrim Word8
bp ByteString
bytes Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
k
  where
    isgraph :: Word8 -> Bool
isgraph = \Word8
w -> Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
W_space Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
W_delete
    bp :: BoundedPrim Word8
bp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
isgraph BoundedPrim Word8
sp BoundedPrim Word8
decEscBP
    sp :: BoundedPrim Word8
sp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
special BoundedPrim Word8
bsEscBP (Word8 -> Word8
toLower (Word8 -> Word8) -> BoundedPrim Word8 -> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP)
    special :: Word8 -> Bool
special = \ case
        Word8
W_dquote -> Bool
True
        Word8
W_bslash -> Bool
True
        Word8
W_dollar -> Bool
True
        Word8
W_open   -> Bool
True
        Word8
W_close  -> Bool
True
        Word8
W_semi   -> Bool
True
        Word8
W_at     -> Bool
True
        Word8
w        -> Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
sep
    toLower :: Word8 -> Word8
toLower Word8
w | Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
W_A Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
25 = Word8
w
              | Bool
otherwise     = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
0x20

-- | Present a 'Net.DNSBase.Domain.Host' label folded to lower case, with the given continuation.
--
presentCSVList :: [SB.ShortByteString]  -- ^ The elements to encode.
               -> Builder               -- ^ Continuation
               -> B.Builder
{-# INLINE presentCSVList #-}
presentCSVList :: [ShortByteString] -> Builder -> Builder
presentCSVList [] = Word8 -> Builder -> Builder
presentByte Word8
W_dquote (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Builder -> Builder
presentByte Word8
W_dquote
presentCSVList (ShortByteString
x : [ShortByteString]
xs) =
    Word8 -> ShortByteString -> Builder -> Builder
pelem Word8
W_dquote ShortByteString
x
    (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> [ShortByteString] -> Builder)
-> [ShortByteString] -> Builder -> Builder
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((ShortByteString -> Builder -> Builder)
-> Builder -> [ShortByteString] -> Builder
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Word8 -> ShortByteString -> Builder -> Builder
pelem Word8
W_comma)) [ShortByteString]
xs
    (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Builder -> Builder
presentByte Word8
W_dquote
  where
    pelem :: Word8 -> ShortByteString -> Builder -> Builder
    pelem :: Word8 -> ShortByteString -> Builder -> Builder
pelem Word8
sep = \ShortByteString
sb Builder
k -> Word8 -> Builder
B.word8 Word8
sep Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> BoundedPrim Word8 -> ByteString -> Builder
P.primMapByteStringBounded BoundedPrim Word8
bp (ShortByteString -> ByteString
SB.fromShort ShortByteString
sb) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
k
    isprint :: Word8 -> Bool
isprint = \Word8
w -> Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
W_space Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
W_delete
    bp :: BoundedPrim Word8
bp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
isprint BoundedPrim Word8
sp BoundedPrim Word8
decEscBP'
    sp :: BoundedPrim Word8
sp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
special BoundedPrim Word8
bsEscBP' BoundedPrim Word8
charBP
    special :: Word8 -> Bool
special = \ case
        Word8
W_dquote -> Bool
True
        Word8
W_bslash -> Bool
True
        Word8
W_comma  -> Bool
True
        Word8
_        -> Bool
False
    -- Two layers of escaping for backslashes and commas, require writing some
    -- backslashes twice:
    -- > "     -> \"
    -- > <DEL> -> \\127
    -- > ,     -> \\,
    -- > \     -> \\\\
    decEscBP' :: BoundedPrim Word8
decEscBP' = (Word8
W_bslash,) (Word8 -> (Word8, Word8))
-> BoundedPrim (Word8, Word8) -> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
decEscBP
    bsEscBP' :: BoundedPrim Word8
bsEscBP'  = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
W_dquote) BoundedPrim Word8
bsEscBP
              (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8 -> BoundedPrim Word8
forall a b. (a -> b) -> a -> b
$ (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
W_bslash) BoundedPrim Word8
bsEsc''' BoundedPrim Word8
bsEsc''
    bsEsc'' :: BoundedPrim Word8
bsEsc''   = (Word8
W_bslash,) ((Word8, Word8) -> (Word8, (Word8, Word8)))
-> (Word8 -> (Word8, Word8)) -> Word8 -> (Word8, (Word8, Word8))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8
W_bslash,)
            (Word8 -> (Word8, (Word8, Word8)))
-> BoundedPrim (Word8, (Word8, Word8)) -> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim (Word8, Word8)
-> BoundedPrim (Word8, (Word8, Word8))
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP
    bsEsc''' :: BoundedPrim Word8
bsEsc'''  = (Word8
W_bslash,) ((Word8, (Word8, Word8)) -> (Word8, (Word8, (Word8, Word8))))
-> (Word8 -> (Word8, (Word8, Word8)))
-> Word8
-> (Word8, (Word8, (Word8, Word8)))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8
W_bslash,) ((Word8, Word8) -> (Word8, (Word8, Word8)))
-> (Word8 -> (Word8, Word8)) -> Word8 -> (Word8, (Word8, Word8))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8
W_bslash,)
            (Word8 -> (Word8, (Word8, (Word8, Word8))))
-> BoundedPrim (Word8, (Word8, (Word8, Word8)))
-> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim (Word8, (Word8, Word8))
-> BoundedPrim (Word8, (Word8, (Word8, Word8)))
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim (Word8, Word8)
-> BoundedPrim (Word8, (Word8, Word8))
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP

------------- Text encoding BoundedPrim helpers

charBP :: P.BoundedPrim Word8
{-# INLINE charBP #-}
charBP :: BoundedPrim Word8
charBP = FixedPrim Word8 -> BoundedPrim Word8
forall a. FixedPrim a -> BoundedPrim a
P.liftFixedToBounded FixedPrim Word8
P.word8

bsEscBP :: P.BoundedPrim Word8
{-# INLINE bsEscBP #-}
bsEscBP :: BoundedPrim Word8
bsEscBP = (Word8
W_bslash,) (Word8 -> (Word8, Word8))
-> BoundedPrim (Word8, Word8) -> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP

decEscBP :: P.BoundedPrim Word8
{-# INLINE decEscBP #-}
decEscBP :: BoundedPrim Word8
decEscBP = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
99) BoundedPrim Word8
dec3 (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8 -> BoundedPrim Word8
forall a b. (a -> b) -> a -> b
$ (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
9) BoundedPrim Word8
dec2 BoundedPrim Word8
dec1
  where
    dec3 :: BoundedPrim Word8
dec3 = (Word8
W_bslash,)
       (Word8 -> (Word8, Word8))
-> BoundedPrim (Word8, Word8) -> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
P.word8Dec
    dec2 :: BoundedPrim Word8
dec2 = (Word8
W_bslash,) ((Word8, Word8) -> (Word8, (Word8, Word8)))
-> (Word8 -> (Word8, Word8)) -> Word8 -> (Word8, (Word8, Word8))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8
W_0,)
       (Word8 -> (Word8, (Word8, Word8)))
-> BoundedPrim (Word8, (Word8, Word8)) -> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim (Word8, Word8)
-> BoundedPrim (Word8, (Word8, Word8))
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
P.word8Dec
    dec1 :: BoundedPrim Word8
dec1 = ((Word8
W_bslash, Word8
W_0),) ((Word8, Word8) -> ((Word8, Word8), (Word8, Word8)))
-> (Word8 -> (Word8, Word8))
-> Word8
-> ((Word8, Word8), (Word8, Word8))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8
W_0,)
       (Word8 -> ((Word8, Word8), (Word8, Word8)))
-> BoundedPrim ((Word8, Word8), (Word8, Word8))
-> BoundedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
>$< (BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
charBP) BoundedPrim (Word8, Word8)
-> BoundedPrim (Word8, Word8)
-> BoundedPrim ((Word8, Word8), (Word8, Word8))
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< (BoundedPrim Word8
charBP BoundedPrim Word8
-> BoundedPrim Word8 -> BoundedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
>*< BoundedPrim Word8
P.word8Dec)
    {-# INLINE dec3 #-}
    {-# INLINE dec2 #-}
    {-# INLINE dec1 #-}

pattern W_space  :: Word8;      pattern $mW_space :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_space :: Word8
W_space  = 0x20
pattern W_dquote :: Word8;      pattern $mW_dquote :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_dquote :: Word8
W_dquote = 0x22
pattern W_dollar :: Word8;      pattern $mW_dollar :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_dollar :: Word8
W_dollar = 0x24
pattern W_open   :: Word8;      pattern $mW_open :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_open :: Word8
W_open   = 0x28
pattern W_close  :: Word8;      pattern $mW_close :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_close :: Word8
W_close  = 0x29
pattern W_comma  :: Word8;      pattern $mW_comma :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_comma :: Word8
W_comma  = 0x2c
pattern W_0      :: Word8;      pattern $mW_0 :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_0 :: Word8
W_0      = 0x30
pattern W_semi   :: Word8;      pattern $mW_semi :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_semi :: Word8
W_semi   = 0x3b
pattern W_at     :: Word8;      pattern $mW_at :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_at :: Word8
W_at     = 0x40
pattern W_A      :: Word8;      pattern $mW_A :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_A :: Word8
W_A      = 0x41
pattern W_bslash :: Word8;      pattern $mW_bslash :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_bslash :: Word8
W_bslash = 0x5c
pattern W_delete :: Word8;      pattern $mW_delete :: forall {r}. Word8 -> ((# #) -> r) -> ((# #) -> r) -> r
$bW_delete :: Word8
W_delete = 0x7f

-----

-- | Supports UTF8 character strings, which are presented like all other
-- character strings, but must be valid UTF8 on the wire, and when unescaped
-- from presentation form.
newtype DnsUtf8Text = DnsUtf8Text T.Text
    deriving (DnsUtf8Text -> DnsUtf8Text -> Bool
(DnsUtf8Text -> DnsUtf8Text -> Bool)
-> (DnsUtf8Text -> DnsUtf8Text -> Bool) -> Eq DnsUtf8Text
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DnsUtf8Text -> DnsUtf8Text -> Bool
== :: DnsUtf8Text -> DnsUtf8Text -> Bool
$c/= :: DnsUtf8Text -> DnsUtf8Text -> Bool
/= :: DnsUtf8Text -> DnsUtf8Text -> Bool
Eq, Eq DnsUtf8Text
Eq DnsUtf8Text =>
(DnsUtf8Text -> DnsUtf8Text -> Ordering)
-> (DnsUtf8Text -> DnsUtf8Text -> Bool)
-> (DnsUtf8Text -> DnsUtf8Text -> Bool)
-> (DnsUtf8Text -> DnsUtf8Text -> Bool)
-> (DnsUtf8Text -> DnsUtf8Text -> Bool)
-> (DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text)
-> (DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text)
-> Ord DnsUtf8Text
DnsUtf8Text -> DnsUtf8Text -> Bool
DnsUtf8Text -> DnsUtf8Text -> Ordering
DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: DnsUtf8Text -> DnsUtf8Text -> Ordering
compare :: DnsUtf8Text -> DnsUtf8Text -> Ordering
$c< :: DnsUtf8Text -> DnsUtf8Text -> Bool
< :: DnsUtf8Text -> DnsUtf8Text -> Bool
$c<= :: DnsUtf8Text -> DnsUtf8Text -> Bool
<= :: DnsUtf8Text -> DnsUtf8Text -> Bool
$c> :: DnsUtf8Text -> DnsUtf8Text -> Bool
> :: DnsUtf8Text -> DnsUtf8Text -> Bool
$c>= :: DnsUtf8Text -> DnsUtf8Text -> Bool
>= :: DnsUtf8Text -> DnsUtf8Text -> Bool
$cmax :: DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text
max :: DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text
$cmin :: DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text
min :: DnsUtf8Text -> DnsUtf8Text -> DnsUtf8Text
Ord, Int -> DnsUtf8Text -> ShowS
[DnsUtf8Text] -> ShowS
DnsUtf8Text -> String
(Int -> DnsUtf8Text -> ShowS)
-> (DnsUtf8Text -> String)
-> ([DnsUtf8Text] -> ShowS)
-> Show DnsUtf8Text
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DnsUtf8Text -> ShowS
showsPrec :: Int -> DnsUtf8Text -> ShowS
$cshow :: DnsUtf8Text -> String
show :: DnsUtf8Text -> String
$cshowList :: [DnsUtf8Text] -> ShowS
showList :: [DnsUtf8Text] -> ShowS
Show)

instance Presentable DnsUtf8Text where
    present :: DnsUtf8Text -> Builder -> Builder
present DnsUtf8Text
t = \ Builder
k ->
        Word8 -> Builder
B.word8 Word8
W_dquote
        Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
encodeUtf8CharString (DnsUtf8Text -> Text
forall a b. Coercible a b => a -> b
coerce DnsUtf8Text
t)
        Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
B.word8 Word8
W_dquote
        Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
k

-- | Support for escaping all non-special characters
-- Based on 'T.encodeUtf8BuilderEscaped'
encodeUtf8CharString :: T.Text -> B.Builder
encodeUtf8CharString :: Text -> Builder
encodeUtf8CharString = \Text
txt -> (forall r. BuildStep r -> BuildStep r) -> Builder
B.builder (Text -> BuildStep r -> BuildStep r
forall r. Text -> BuildStep r -> BuildStep r
mkBuildstep Text
txt)
  where
    printable :: Word8 -> Bool
printable = \Word8
w -> Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
W_space Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
W_delete
    bp :: BoundedPrim Word8
bp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
printable BoundedPrim Word8
sp BoundedPrim Word8
decEscBP
    sp :: BoundedPrim Word8
sp = (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB Word8 -> Bool
special BoundedPrim Word8
bsEscBP BoundedPrim Word8
charBP
    special :: Word8 -> Bool
special = \ case
        Word8
W_dquote -> Bool
True
        Word8
W_bslash -> Bool
True
        Word8
_        -> Bool
False
    bound :: Int
bound = BoundedPrim Word8 -> Int
forall a. BoundedPrim a -> Int
P.sizeBound BoundedPrim Word8
bp

    mkBuildstep :: T.Text -> B.BuildStep r -> B.BuildStep r
    mkBuildstep :: forall r. Text -> BuildStep r -> BuildStep r
mkBuildstep (T.Text ByteArray
arr Int
off Int
len) !BuildStep r
k =
        Int -> BuildStep r
outerLoop Int
off
      where
        iend :: Int
iend = Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len

        outerLoop :: Int -> BuildStep r
outerLoop !Int
i0 !br :: BufferRange
br@(B.BufferRange Ptr Word8
op0 Ptr Word8
ope)
          | Int
i0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
iend       = BuildStep r
k BufferRange
br
          | Int
outRemaining Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Int -> IO (BuildSignal r)
goPartial (Int
i0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
outRemaining Int
inpRemaining)
          | Bool
otherwise        = BuildSignal r -> IO (BuildSignal r)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (BuildSignal r -> IO (BuildSignal r))
-> BuildSignal r -> IO (BuildSignal r)
forall a b. (a -> b) -> a -> b
$ Int -> Ptr Word8 -> BuildStep r -> BuildSignal r
forall a. Int -> Ptr Word8 -> BuildStep a -> BuildSignal a
B.bufferFull Int
bound Ptr Word8
op0 (Int -> BuildStep r
outerLoop Int
i0)
          where
            outRemaining :: Int
outRemaining = (Ptr Word8
ope Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
op0) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
bound
            inpRemaining :: Int
inpRemaining = Int
iend Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i0

            goPartial :: Int -> IO (BuildSignal r)
goPartial !Int
iendTmp = Int -> Ptr Word8 -> IO (BuildSignal r)
go Int
i0 Ptr Word8
op0
              where
                go :: Int -> Ptr Word8 -> IO (BuildSignal r)
go !Int
i !Ptr Word8
op
                  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
iendTmp = do
                    let w :: Word8
w = ByteArray -> Int -> Word8
TA.unsafeIndex ByteArray
arr Int
i
                    BoundedPrim Word8 -> Word8 -> Ptr Word8 -> IO (Ptr Word8)
forall a. BoundedPrim a -> a -> Ptr Word8 -> IO (Ptr Word8)
P.runB BoundedPrim Word8
bp Word8
w Ptr Word8
op IO (Ptr Word8)
-> (Ptr Word8 -> IO (BuildSignal r)) -> IO (BuildSignal r)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> Ptr Word8 -> IO (BuildSignal r)
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
                  | Bool
otherwise = Int -> BuildStep r
outerLoop Int
i (Ptr Word8 -> Ptr Word8 -> BufferRange
B.BufferRange Ptr Word8
op Ptr Word8
ope)