{-|
Module      : Net.DNSBase.RData.SRV
Description : Service-endpoint and locator records (MX, SRV, AFSDB, NAPTR, NID/L32/L64/LP, AMTRELAY)
Copyright   : (c) Viktor Dukhovni, 2026
License     : BSD-3-Clause
Maintainer  : ietf-dane@dukhovni.org
Stability   : unstable

This module gathers RR types that map a name to a service
endpoint or address locator.  'T_mx' (RFC 1035), 'T_srv'
(RFC 2782), 'T_afsdb' (RFC 1183), and 'T_naptr' (RFC 3403) are
pre-RFC-4034 records pointing at a host via a domain name;
canonical RDATA lower-cases the embedded domain.  The ILNP
family ('T_nid', 'T_l32', 'T_l64', 'T_lp'; RFC 6742) and
'T_amtrelay' (RFC 8777) are later records — those with a
domain field treat it case-sensitively in canonical form per
RFC 6840 section 5.1.
-}
{-# LANGUAGE
    MagicHash
  , RecordWildCards
  , UndecidableInstances
  #-}

module Net.DNSBase.RData.SRV
    ( T_mx(..)
    , T_srv(..)
    , T_afsdb(..)
    , T_naptr(..)
      -- * NID and L64
    , X_nid(.., T_NID, T_L64)
    , type XnidConName, T_nid, T_l64
      -- *** 'T_NID' fields
    , nidPref
    , nidAddr
      -- *** 'T_L64' fields
    , l64Pref
    , l64Addr
      -- * L32
    , T_l32(..)
      -- * LP
    , T_lp(..)
      -- * AMTRELAY
    , T_amtrelay(..)
    , AmtRelay(Amt_Nil, Amt_A, Amt_AAAA, Amt_Host, Amt_Opaque)
    ) where

import qualified Data.ByteString.Short as SB
import Data.ByteString.Builder (char8, word8HexFixed, word16HexFixed)
import GHC.Exts (proxy#)
import GHC.TypeLits as TL (TypeError, ErrorMessage(..))
import GHC.TypeLits (KnownSymbol, Symbol, symbolVal')

import Net.DNSBase.Internal.Util
import Net.DNSBase.Internal.Bytes

import Net.DNSBase.Decode.Domain
import Net.DNSBase.Decode.State
import Net.DNSBase.Domain
import Net.DNSBase.Encode.Metric
import Net.DNSBase.Encode.State
import Net.DNSBase.Nat16
import Net.DNSBase.Present
import Net.DNSBase.RData
import Net.DNSBase.RRTYPE
import Net.DNSBase.Text

type XnidConName :: Nat -> Symbol
type family XnidConName n where
    XnidConName N_nid = "T_NID"
    XnidConName N_l64 = "T_L64"
    XnidConName n     = TypeError
                        ( ShowType n
                          :<>: TL.Text " is not a NID or L64 RRTYPE" )

-- | X_nid specialised to @NID@ records.
type T_nid = X_nid N_nid
-- | X_nid specialised to @L64@ records.
type T_l64 = X_nid N_l64

-- | Record pattern synonym viewing the shared 'X_nid' record as an
-- @NID@ (Node Identifier) record, RFC 6742.  Fields: 'nidPref',
-- 'nidAddr'.  Not coercible to/from 'T_l64': the role of 'X_nid' is
-- /nominal/ because the 64-bit payload means a Node-ID here and a
-- 64-bit locator prefix in L64.
pattern T_NID :: Word16 -- ^ Preference
              -> Word64 -- ^ Node Identifier
              -> T_nid
pattern $mT_NID :: forall {r}. T_nid -> (Word16 -> Word64 -> r) -> ((# #) -> r) -> r
$bT_NID :: Word16 -> Word64 -> T_nid
T_NID { T_nid -> Word16
nidPref, T_nid -> Word64
nidAddr } = (X_NID nidPref nidAddr :: T_nid)
{-# COMPLETE T_NID #-}

-- | Record pattern synonym viewing the shared 'X_nid' record as an
-- @L64@ (64-bit locator) record, RFC 6742.  Fields: 'l64Pref',
-- 'l64Addr'.  Not coercible to/from 'T_nid' (see 'T_NID' note).
pattern T_L64 :: Word16 -- ^ Preference
              -> Word64 -- ^ 64-bit locator prefix
              -> T_l64
pattern $mT_L64 :: forall {r}. T_l64 -> (Word16 -> Word64 -> r) -> ((# #) -> r) -> r
$bT_L64 :: Word16 -> Word64 -> T_l64
T_L64 { T_l64 -> Word16
l64Pref, T_l64 -> Word64
l64Addr } = (X_NID l64Pref l64Addr :: T_l64)
{-# COMPLETE T_L64 #-}

-- | The @MX@ resource record
-- ([RFC 1035 section 3.3.9](https://datatracker.ietf.org/doc/html/rfc1035#section-3.3.9))
-- — a mail exchanger for the owner name: a 16-bit preference
-- (lower is preferred) and a 'Domain' naming the exchange host.
--
-- >  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- >  |                  PREFERENCE                   |
-- >  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- >  /                   EXCHANGE                    /
-- >  /                                               /
-- >  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
--
-- The exchange field is subject to wire-form name compression on
-- encode
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4))
-- and canonicalises to lower case
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
-- The 'Eq' and 'Ord' instances compare the exchange in canonical
-- wire form (via 'equalWireHost' / 'compareWireHost'), so 'Ord'
-- is canonical.
--
-- A name that resolves to a CNAME should not be used in the
-- exchange field
-- ([RFC 2181 section 10.3](https://datatracker.ietf.org/doc/html/rfc2181#section-10.3),
-- [RFC 5321 section 5.1](https://datatracker.ietf.org/doc/html/rfc5321#section-5.1)).
data T_mx = T_MX
    { T_mx -> Word16
mxPref :: Word16 -- ^ Preference, lower is better
    , T_mx -> Domain
mxExch :: Domain -- ^ Exchange host.
    } deriving (Int -> T_mx -> ShowS
[T_mx] -> ShowS
T_mx -> String
(Int -> T_mx -> ShowS)
-> (T_mx -> String) -> ([T_mx] -> ShowS) -> Show T_mx
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_mx -> ShowS
showsPrec :: Int -> T_mx -> ShowS
$cshow :: T_mx -> String
show :: T_mx -> String
$cshowList :: [T_mx] -> ShowS
showList :: [T_mx] -> ShowS
Show)

-- | Case-insensitive wire-form equality.
instance Eq T_mx where
    T_mx
a == :: T_mx -> T_mx -> Bool
== T_mx
b = (T_mx -> Word16
mxPref T_mx
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_mx -> Word16
mxPref T_mx
b)
          Bool -> Bool -> Bool
&& (T_mx -> Domain
mxExch T_mx
a) Domain -> Domain -> Bool
`equalWireHost` (T_mx -> Domain
mxExch T_mx
b)

-- | Case-insensitive wire-form order.
instance Ord T_mx where
    compare :: T_mx -> T_mx -> Ordering
compare T_mx
a T_mx
b = (T_mx -> Word16
mxPref T_mx
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_mx -> Word16
mxPref T_mx
b)
               Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_mx -> Domain
mxExch T_mx
a) Domain -> Domain -> Ordering
`compareWireHost` (T_mx -> Domain
mxExch T_mx
b)

instance Presentable T_mx where
    present :: T_mx -> Builder -> Builder
present T_MX{Word16
Domain
mxPref :: T_mx -> Word16
mxExch :: T_mx -> Domain
mxPref :: Word16
mxExch :: Domain
..} = Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
mxPref (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Domain
mxExch

instance KnownRData T_mx where
    rdType :: forall b -> (b ~ T_mx) => RRTYPE
rdType _ = RRTYPE
MX
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_mx -> SPut s RData
rdEncode T_MX{Word16
Domain
mxPref :: T_mx -> Word16
mxExch :: T_mx -> Domain
mxPref :: Word16
mxExch :: Domain
..} = do
        Word16 -> SPut s RData
forall r s. ErrorContext r => Word16 -> SPut s r
put16 Word16
mxPref
        -- Subject to name compression.
        Domain -> SPut s RData
forall r s. ErrorContext r => Domain -> SPut s r
putDomain Domain
mxExch
    cnEncode :: forall s. T_mx -> SPut s RData
cnEncode T_MX{Word16
Domain
mxPref :: T_mx -> Word16
mxExch :: T_mx -> Domain
mxPref :: Word16
mxExch :: Domain
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
        Word16 -> SizedBuilder
mbWord16 Word16
mxPref
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm (Domain -> Domain
canonicalise Domain
mxExch)
    rdDecode :: forall b ->
(b ~ T_mx) => RDataExtensionVal T_mx -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_mx
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        mxPref <- SGet Word16
get16
        -- Subject to name compression.
        mxExch <- getDomain
        return $ RData $ T_MX{..}

-- | The @SRV@ resource record
-- ([RFC 2782](https://datatracker.ietf.org/doc/html/rfc2782))
-- — names the location of a service: 16-bit priority, weight,
-- and port, plus a 'Domain' naming the target host.
--
-- The target field is not subject to wire-form name compression
-- on encode
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4))
-- but compression is tolerated on decode.  It canonicalises to
-- lower case
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
-- The 'Eq' and 'Ord' instances compare the target in canonical
-- wire form (via 'equalWireHost' / 'compareWireHost'), so 'Ord'
-- is canonical.
data T_srv = T_SRV
    { T_srv -> Word16
srvPriority :: Word16
    , T_srv -> Word16
srvWeight   :: Word16
    , T_srv -> Word16
srvPort     :: Word16
    , T_srv -> Domain
srvTarget   :: Domain -- not subject to name compression
    } deriving (Int -> T_srv -> ShowS
[T_srv] -> ShowS
T_srv -> String
(Int -> T_srv -> ShowS)
-> (T_srv -> String) -> ([T_srv] -> ShowS) -> Show T_srv
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_srv -> ShowS
showsPrec :: Int -> T_srv -> ShowS
$cshow :: T_srv -> String
show :: T_srv -> String
$cshowList :: [T_srv] -> ShowS
showList :: [T_srv] -> ShowS
Show)

-- | Equality is not case-senstive on the target host name.
instance Eq T_srv where
    T_srv
a == :: T_srv -> T_srv -> Bool
== T_srv
b = (T_srv -> Word16
srvPriority T_srv
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_srv -> Word16
srvPriority T_srv
b)
          Bool -> Bool -> Bool
&& (T_srv -> Word16
srvWeight   T_srv
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_srv -> Word16
srvWeight   T_srv
b)
          Bool -> Bool -> Bool
&& (T_srv -> Word16
srvPort     T_srv
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_srv -> Word16
srvPort     T_srv
b)
          Bool -> Bool -> Bool
&& (T_srv -> Domain
srvTarget   T_srv
a) Domain -> Domain -> Bool
`equalWireHost` (T_srv -> Domain
srvTarget   T_srv
b)

-- | Order is not case-senstive on the target host name.
instance Ord T_srv where
    T_srv
a compare :: T_srv -> T_srv -> Ordering
`compare` T_srv
b = (T_srv -> Word16
srvPriority T_srv
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_srv -> Word16
srvPriority T_srv
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_srv -> Word16
srvWeight   T_srv
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_srv -> Word16
srvWeight   T_srv
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_srv -> Word16
srvPort     T_srv
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_srv -> Word16
srvPort     T_srv
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_srv -> Domain
srvTarget   T_srv
a) Domain -> Domain -> Ordering
`compareWireHost` (T_srv -> Domain
srvTarget   T_srv
b)

instance Presentable T_srv where
    present :: T_srv -> Builder -> Builder
present T_SRV{Word16
Domain
srvPriority :: T_srv -> Word16
srvWeight :: T_srv -> Word16
srvPort :: T_srv -> Word16
srvTarget :: T_srv -> Domain
srvPriority :: Word16
srvWeight :: Word16
srvPort :: Word16
srvTarget :: Domain
..} =
        Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
srvPriority
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Word16
srvWeight
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Word16
srvPort
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Domain
srvTarget

instance KnownRData T_srv where
    rdType :: forall b -> (b ~ T_srv) => RRTYPE
rdType _ = RRTYPE
SRV
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_srv -> SPut s RData
rdEncode T_SRV{Word16
Domain
srvPriority :: T_srv -> Word16
srvWeight :: T_srv -> Word16
srvPort :: T_srv -> Word16
srvTarget :: T_srv -> Domain
srvPriority :: Word16
srvWeight :: Word16
srvPort :: Word16
srvTarget :: Domain
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
        Word16 -> SizedBuilder
mbWord16 Word16
srvPriority
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word16 -> SizedBuilder
mbWord16 Word16
srvWeight
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word16 -> SizedBuilder
mbWord16 Word16
srvPort
        -- No Name compression when encoding.
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
srvTarget
    cnEncode :: forall s. T_srv -> SPut s RData
cnEncode rd :: T_srv
rd@(T_SRV{srvTarget :: T_srv -> Domain
srvTarget = Domain
t}) =
        T_srv -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_srv -> SPut s RData
rdEncode T_srv
rd { srvTarget = canonicalise t }
    rdDecode :: forall b ->
(b ~ T_srv) => RDataExtensionVal T_srv -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_srv
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        srvPriority <- SGet Word16
get16
        srvWeight   <- get16
        srvPort     <- get16
        -- Name compression accepted when decoding.
        srvTarget   <- getDomain
        return $ RData $ T_SRV{..}

-- | The @AFSDB@ resource record
-- ([RFC 1183 section 1](https://datatracker.ietf.org/doc/html/rfc1183#section-1);
-- see also
-- [RFC 5864 section 5](https://tools.ietf.org/html/rfc5864#section-5))
-- — points at an AFS-cell or DCE-authentication-cell server:
-- a 16-bit subtype tag and a 'Domain' hostname.
--
-- The hostname field is not subject to wire-form name compression
-- on encode but compression is tolerated on decode.  It
-- canonicalises to lower case
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
-- The 'Eq' and 'Ord' instances compare the hostname in canonical
-- wire form (via 'equalWireHost' / 'compareWireHost'), so 'Ord'
-- is canonical.
data T_afsdb = T_AFSDB
    { T_afsdb -> Word16
afsdbSubtype  :: Word16
    , T_afsdb -> Domain
afsdbHostname :: Domain
    } deriving (Int -> T_afsdb -> ShowS
[T_afsdb] -> ShowS
T_afsdb -> String
(Int -> T_afsdb -> ShowS)
-> (T_afsdb -> String) -> ([T_afsdb] -> ShowS) -> Show T_afsdb
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_afsdb -> ShowS
showsPrec :: Int -> T_afsdb -> ShowS
$cshow :: T_afsdb -> String
show :: T_afsdb -> String
$cshowList :: [T_afsdb] -> ShowS
showList :: [T_afsdb] -> ShowS
Show)

instance Eq T_afsdb where
    T_afsdb
a == :: T_afsdb -> T_afsdb -> Bool
== T_afsdb
b = (T_afsdb -> Word16
afsdbSubtype  T_afsdb
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
== (T_afsdb -> Word16
afsdbSubtype  T_afsdb
b)
          Bool -> Bool -> Bool
&& (T_afsdb -> Domain
afsdbHostname T_afsdb
a) Domain -> Domain -> Bool
`equalWireHost` (T_afsdb -> Domain
afsdbHostname T_afsdb
b)

instance Ord T_afsdb where
    T_afsdb
a compare :: T_afsdb -> T_afsdb -> Ordering
`compare` T_afsdb
b = (T_afsdb -> Word16
afsdbSubtype  T_afsdb
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_afsdb -> Word16
afsdbSubtype  T_afsdb
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_afsdb -> Domain
afsdbHostname T_afsdb
a) Domain -> Domain -> Ordering
`compareWireHost` (T_afsdb -> Domain
afsdbHostname T_afsdb
b)

instance Presentable T_afsdb where
    present :: T_afsdb -> Builder -> Builder
present T_AFSDB{Word16
Domain
afsdbSubtype :: T_afsdb -> Word16
afsdbHostname :: T_afsdb -> Domain
afsdbSubtype :: Word16
afsdbHostname :: Domain
..} =
        Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
afsdbSubtype
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Domain
afsdbHostname

instance KnownRData T_afsdb where
    rdType :: forall b -> (b ~ T_afsdb) => RRTYPE
rdType _ = RRTYPE
AFSDB
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_afsdb -> SPut s RData
rdEncode T_AFSDB{Word16
Domain
afsdbSubtype :: T_afsdb -> Word16
afsdbHostname :: T_afsdb -> Domain
afsdbSubtype :: Word16
afsdbHostname :: Domain
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
        Word16 -> SizedBuilder
mbWord16 Word16
afsdbSubtype
        -- No Name compression when encoding.
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
afsdbHostname
    cnEncode :: forall s. T_afsdb -> SPut s RData
cnEncode T_AFSDB{Word16
Domain
afsdbSubtype :: T_afsdb -> Word16
afsdbHostname :: T_afsdb -> Domain
afsdbSubtype :: Word16
afsdbHostname :: Domain
..} =
        T_afsdb -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_afsdb -> SPut s RData
rdEncode (T_afsdb -> SPut s RData) -> T_afsdb -> SPut s RData
forall a b. (a -> b) -> a -> b
$ Word16 -> Domain -> T_afsdb
T_AFSDB Word16
afsdbSubtype
                           (Domain -> Domain
canonicalise Domain
afsdbHostname)
    rdDecode :: forall b ->
(b ~ T_afsdb) => RDataExtensionVal T_afsdb -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_afsdb
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        afsdbSubtype  <- SGet Word16
get16
        -- Name compression accepted when decoding.
        afsdbHostname <- getDomain
        return $ RData $ T_AFSDB{..}

-- | The @NAPTR@ resource record
-- ([RFC 3403 section 4](https://www.rfc-editor.org/rfc/rfc3403.html#section-4))
-- — Naming Authority Pointer: a rewriting rule that translates
-- the owner name into another resource via the flags/services
-- tags, an optional regexp, and a replacement domain.
--
-- >                                 1  1  1  1  1  1
-- >   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > |                     ORDER                     |
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > |                   PREFERENCE                  |
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                     FLAGS                     /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                   SERVICES                    /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                    REGEXP                     /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                  REPLACEMENT                  /
-- > /                                               /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
--
-- The replacement field is not subject to wire-form name
-- compression on encode but compression is tolerated on decode.
-- It canonicalises to lower case
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
-- The 'Eq' and 'Ord' instances compare the replacement in
-- canonical wire form (via 'equalWireHost' / 'compareWireHost')
-- and the character-string fields as DNS character-strings, so
-- 'Ord' is canonical.
data T_naptr = T_NAPTR
    { T_naptr -> Word16
naptrOrder       :: Word16
    , T_naptr -> Word16
naptrPreference  :: Word16
    , T_naptr -> ShortByteString
naptrFlags       :: ShortByteString
    , T_naptr -> ShortByteString
naptrServices    :: ShortByteString
    , T_naptr -> ShortByteString
naptrRegexp      :: ShortByteString
    , T_naptr -> Domain
naptrReplacement :: Domain
    } deriving (Int -> T_naptr -> ShowS
[T_naptr] -> ShowS
T_naptr -> String
(Int -> T_naptr -> ShowS)
-> (T_naptr -> String) -> ([T_naptr] -> ShowS) -> Show T_naptr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_naptr -> ShowS
showsPrec :: Int -> T_naptr -> ShowS
$cshow :: T_naptr -> String
show :: T_naptr -> String
$cshowList :: [T_naptr] -> ShowS
showList :: [T_naptr] -> ShowS
Show)

-- | Equality is not case-senstive on the replacement domain.
instance Eq T_naptr where
    T_naptr
a == :: T_naptr -> T_naptr -> Bool
== T_naptr
b = (T_naptr -> Word16
naptrOrder       T_naptr
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_naptr -> Word16
naptrOrder       T_naptr
b)
          Bool -> Bool -> Bool
&& (T_naptr -> Word16
naptrPreference  T_naptr
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_naptr -> Word16
naptrPreference  T_naptr
b)
          Bool -> Bool -> Bool
&& (T_naptr -> ShortByteString
naptrFlags       T_naptr
a) ShortByteString -> ShortByteString -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_naptr -> ShortByteString
naptrFlags       T_naptr
b)
          Bool -> Bool -> Bool
&& (T_naptr -> ShortByteString
naptrServices    T_naptr
a) ShortByteString -> ShortByteString -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_naptr -> ShortByteString
naptrServices    T_naptr
b)
          Bool -> Bool -> Bool
&& (T_naptr -> ShortByteString
naptrRegexp      T_naptr
a) ShortByteString -> ShortByteString -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_naptr -> ShortByteString
naptrRegexp      T_naptr
b)
          Bool -> Bool -> Bool
&& (T_naptr -> Domain
naptrReplacement T_naptr
a) Domain -> Domain -> Bool
`equalWireHost` (T_naptr -> Domain
naptrReplacement T_naptr
b)

-- | Order is not case-senstive on the replacement domain.
instance Ord T_naptr where
    T_naptr
a compare :: T_naptr -> T_naptr -> Ordering
`compare` T_naptr
b = (T_naptr -> Word16
naptrOrder       T_naptr
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_naptr -> Word16
naptrOrder       T_naptr
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_naptr -> Word16
naptrPreference  T_naptr
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_naptr -> Word16
naptrPreference  T_naptr
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_naptr -> ShortByteString
naptrFlags       T_naptr
a) ShortByteString -> ShortByteString -> Ordering
`strCompare`      (T_naptr -> ShortByteString
naptrFlags       T_naptr
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_naptr -> ShortByteString
naptrServices    T_naptr
a) ShortByteString -> ShortByteString -> Ordering
`strCompare`      (T_naptr -> ShortByteString
naptrServices    T_naptr
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_naptr -> ShortByteString
naptrRegexp      T_naptr
a) ShortByteString -> ShortByteString -> Ordering
`strCompare`      (T_naptr -> ShortByteString
naptrRegexp      T_naptr
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_naptr -> Domain
naptrReplacement T_naptr
a) Domain -> Domain -> Ordering
`compareWireHost` (T_naptr -> Domain
naptrReplacement T_naptr
b)
      where
        strCompare :: ShortByteString -> ShortByteString -> Ordering
strCompare = (ShortByteString -> DnsText)
-> ShortByteString -> ShortByteString -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing ShortByteString -> DnsText
DnsText

instance Presentable T_naptr where
    present :: T_naptr -> Builder -> Builder
present T_NAPTR{Word16
ShortByteString
Domain
naptrOrder :: T_naptr -> Word16
naptrPreference :: T_naptr -> Word16
naptrFlags :: T_naptr -> ShortByteString
naptrServices :: T_naptr -> ShortByteString
naptrRegexp :: T_naptr -> ShortByteString
naptrReplacement :: T_naptr -> Domain
naptrOrder :: Word16
naptrPreference :: Word16
naptrFlags :: ShortByteString
naptrServices :: ShortByteString
naptrRegexp :: ShortByteString
naptrReplacement :: Domain
..} =
        Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present     Word16
naptrOrder
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Word16
naptrPreference
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @DnsText (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
naptrFlags)
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @DnsText (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
naptrServices)
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @DnsText (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
naptrRegexp)
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Domain
naptrReplacement

instance KnownRData T_naptr where
    rdType :: forall b -> (b ~ T_naptr) => RRTYPE
rdType _ = RRTYPE
NAPTR
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_naptr -> SPut s RData
rdEncode T_NAPTR{Word16
ShortByteString
Domain
naptrOrder :: T_naptr -> Word16
naptrPreference :: T_naptr -> Word16
naptrFlags :: T_naptr -> ShortByteString
naptrServices :: T_naptr -> ShortByteString
naptrRegexp :: T_naptr -> ShortByteString
naptrReplacement :: T_naptr -> Domain
naptrOrder :: Word16
naptrPreference :: Word16
naptrFlags :: ShortByteString
naptrServices :: ShortByteString
naptrRegexp :: ShortByteString
naptrReplacement :: Domain
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
           Word16 -> SizedBuilder
mbWord16              Word16
naptrOrder
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word16 -> SizedBuilder
mbWord16              Word16
naptrPreference
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
naptrFlags
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
naptrServices
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
naptrRegexp
           -- no name compression
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm            Domain
naptrReplacement
    cnEncode :: forall s. T_naptr -> SPut s RData
cnEncode rd :: T_naptr
rd@(T_NAPTR{naptrReplacement :: T_naptr -> Domain
naptrReplacement = Domain
r}) =
        T_naptr -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_naptr -> SPut s RData
rdEncode T_naptr
rd { naptrReplacement = canonicalise r }
    rdDecode :: forall b ->
(b ~ T_naptr) => RDataExtensionVal T_naptr -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_naptr
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        naptrOrder       <- SGet Word16
get16
        naptrPreference  <- get16
        naptrFlags       <- getShortByteStringLen8
        naptrServices    <- getShortByteStringLen8
        naptrRegexp      <- getShortByteStringLen8
           -- possible name decompression
        naptrReplacement <- getDomain
        return $ RData $ T_NAPTR{..}

-- | Shared wire-format representation for ILNP node-identifier
-- and locator records: @NID@
-- ([RFC 6742 section 2.1.1](https://www.rfc-editor.org/rfc/rfc6742.html#section-2.1.1))
-- carries a 64-bit Node-ID, and @L64@
-- ([RFC 6742 section 2.3.1](https://www.rfc-editor.org/rfc/rfc6742.html#section-2.3.1))
-- carries a 64-bit IPv6 locator prefix.  The type parameter @n@
-- (either 'N_nid' or 'N_l64') determines the RR type.  Each has
-- its own type synonym ('T_nid', 'T_l64') and matching record
-- pattern synonym ('T_NID', 'T_L64') with the corresponding
-- field-name prefix (@nid@, @l64@).  The role of 'X_nid' is
-- /nominal/: the 64-bit payload means different things in each,
-- so 'T_nid' and 'T_l64' are not coercible.
--
-- Derived 'Ord' is canonical: no embedded domain, fields compared
-- in wire-encoding order.  See 'T_l32' and 'T_lp' for the rest
-- of the ILNP record family.
--
-- >   0                   1                   2                   3
-- >   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-- >  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- >  |          Preference           |                               |
-- >  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-- >  |                             NodeID                            |
-- >  +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- >  |                               |
-- >  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
type X_nid :: Nat -> Type
type role X_nid nominal
data X_nid n = X_NID
    { forall (n :: Nat). X_nid n -> Word16
_nidPref :: Word16 -- ^ Preference
    , forall (n :: Nat). X_nid n -> Word64
_nidAddr :: Word64 -- ^ Node ID or 64-bit IPv6 prefix
    }
deriving instance (KnownSymbol (XnidConName n)) => Eq (X_nid n)
deriving instance (KnownSymbol (XnidConName n)) => Ord (X_nid n)

instance (Nat16 n, KnownSymbol (XnidConName n)) => Show (X_nid n) where
    showsPrec :: Int -> X_nid n -> ShowS
showsPrec Int
p X_NID{Word16
Word64
_nidPref :: forall (n :: Nat). X_nid n -> Word16
_nidAddr :: forall (n :: Nat). X_nid n -> Word64
_nidPref :: Word16
_nidAddr :: Word64
..} = Int -> ShowS -> ShowS
showsP Int
p (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString (Proxy# (XnidConName n) -> String
forall (n :: Symbol). KnownSymbol n => Proxy# n -> String
symbolVal' (forall {k} (a :: k). Proxy# a
forall (a :: Symbol). Proxy# a
proxy# @(XnidConName n)))
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> ShowS
forall a. Show a => a -> ShowS
shows' Word16
_nidPref
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> ShowS
forall a. Show a => a -> ShowS
shows' Word64
_nidAddr

instance (KnownSymbol (XnidConName n)) => Presentable (X_nid n) where
    present :: X_nid n -> Builder -> Builder
present X_NID{Word16
Word64
_nidPref :: forall (n :: Nat). X_nid n -> Word16
_nidAddr :: forall (n :: Nat). X_nid n -> Word64
_nidPref :: Word16
_nidAddr :: Word64
..} =
        Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
_nidPref
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \Builder
k -> Char -> Int -> Builder
bld Char
' ' Int
48 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Int -> Builder
bld Char
':' Int
32 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Int -> Builder
bld Char
':' Int
16 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Int -> Builder
bld Char
':'  Int
0 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
k
      where
        bld :: Char -> Int -> Builder
        bld :: Char -> Int -> Builder
bld Char
sep Int
shft = Char -> Builder
char8 Char
sep Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
            (Word16 -> Builder
word16HexFixed (Word16 -> Builder) -> Word16 -> Builder
forall a b. (a -> b) -> a -> b
$ Word64 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word16) -> Word64 -> Word16
forall a b. (a -> b) -> a -> b
$ Word64
_nidAddr Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
shft)

instance (Nat16 n, KnownSymbol (XnidConName n)) => KnownRData (X_nid n) where
    rdType :: forall b -> (b ~ X_nid n) => RRTYPE
rdType _ = Word16 -> RRTYPE
RRTYPE (Word16 -> RRTYPE) -> Word16 -> RRTYPE
forall a b. (a -> b) -> a -> b
$ natToWord16 n
    {-# INLINE rdType #-}
    rdEncode :: forall s. X_nid n -> SPut s RData
rdEncode X_NID{Word16
Word64
_nidPref :: forall (n :: Nat). X_nid n -> Word16
_nidAddr :: forall (n :: Nat). X_nid n -> Word64
_nidPref :: Word16
_nidAddr :: Word64
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
           Word16 -> SizedBuilder
mbWord16              Word16
_nidPref
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word64 -> SizedBuilder
mbWord64              Word64
_nidAddr
    rdDecode :: forall b ->
(b ~ X_nid n) => RDataExtensionVal (X_nid n) -> Int -> SGet RData
rdDecode _ RDataExtensionVal (X_nid n)
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        _nidPref          <- SGet Word16
get16
        _nidAddr          <- get64
        pure $ RData (X_NID{..} :: X_nid n)

-- | The @L32@ resource record
-- ([RFC 6742 section 2.2.1](https://www.rfc-editor.org/rfc/rfc6742.html#section-2.2.1))
-- — an ILNP 32-bit locator: a 16-bit preference and a 32-bit
-- network locator carried in an 'IPv4' value.
--
-- >  0                   1                   2                   3
-- >  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |          Preference           |      Locator32 (16 MSBs)      |
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |     Locator32 (16 LSBs)       |
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
-- Derived 'Ord' is canonical: no embedded domain, fields compared
-- in wire-encoding order.  See 'X_nid' and 'T_lp' for the rest
-- of the ILNP record family.
data T_l32 = T_L32
    { T_l32 -> Word16
l32Pref :: Word16
    , T_l32 -> IPv4
l32Addr :: IPv4
    } deriving (T_l32 -> T_l32 -> Bool
(T_l32 -> T_l32 -> Bool) -> (T_l32 -> T_l32 -> Bool) -> Eq T_l32
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_l32 -> T_l32 -> Bool
== :: T_l32 -> T_l32 -> Bool
$c/= :: T_l32 -> T_l32 -> Bool
/= :: T_l32 -> T_l32 -> Bool
Eq, Eq T_l32
Eq T_l32 =>
(T_l32 -> T_l32 -> Ordering)
-> (T_l32 -> T_l32 -> Bool)
-> (T_l32 -> T_l32 -> Bool)
-> (T_l32 -> T_l32 -> Bool)
-> (T_l32 -> T_l32 -> Bool)
-> (T_l32 -> T_l32 -> T_l32)
-> (T_l32 -> T_l32 -> T_l32)
-> Ord T_l32
T_l32 -> T_l32 -> Bool
T_l32 -> T_l32 -> Ordering
T_l32 -> T_l32 -> T_l32
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 :: T_l32 -> T_l32 -> Ordering
compare :: T_l32 -> T_l32 -> Ordering
$c< :: T_l32 -> T_l32 -> Bool
< :: T_l32 -> T_l32 -> Bool
$c<= :: T_l32 -> T_l32 -> Bool
<= :: T_l32 -> T_l32 -> Bool
$c> :: T_l32 -> T_l32 -> Bool
> :: T_l32 -> T_l32 -> Bool
$c>= :: T_l32 -> T_l32 -> Bool
>= :: T_l32 -> T_l32 -> Bool
$cmax :: T_l32 -> T_l32 -> T_l32
max :: T_l32 -> T_l32 -> T_l32
$cmin :: T_l32 -> T_l32 -> T_l32
min :: T_l32 -> T_l32 -> T_l32
Ord, Int -> T_l32 -> ShowS
[T_l32] -> ShowS
T_l32 -> String
(Int -> T_l32 -> ShowS)
-> (T_l32 -> String) -> ([T_l32] -> ShowS) -> Show T_l32
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_l32 -> ShowS
showsPrec :: Int -> T_l32 -> ShowS
$cshow :: T_l32 -> String
show :: T_l32 -> String
$cshowList :: [T_l32] -> ShowS
showList :: [T_l32] -> ShowS
Show)

instance Presentable T_l32 where
    present :: T_l32 -> Builder -> Builder
present T_L32{Word16
IPv4
l32Pref :: T_l32 -> Word16
l32Addr :: T_l32 -> IPv4
l32Pref :: Word16
l32Addr :: IPv4
..} = Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
l32Pref (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IPv4 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp IPv4
l32Addr

instance KnownRData T_l32 where
    rdType :: forall b -> (b ~ T_l32) => RRTYPE
rdType _ = RRTYPE
L32
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_l32 -> SPut s RData
rdEncode T_L32{Word16
IPv4
l32Pref :: T_l32 -> Word16
l32Addr :: T_l32 -> IPv4
l32Pref :: Word16
l32Addr :: IPv4
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
           Word16 -> SizedBuilder
mbWord16              Word16
l32Pref
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word32 -> SizedBuilder
mbWord32              (IPv4 -> Word32
fromIPv4w IPv4
l32Addr)
    rdDecode :: forall b ->
(b ~ T_l32) => RDataExtensionVal T_l32 -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_l32
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        l32Pref          <- SGet Word16
get16
        l32Addr          <- toIPv4w <$> get32
        pure $ RData $ T_L32{..}


-- | The @LP@ resource record
-- ([RFC 6742 section 2.4.1](https://www.rfc-editor.org/rfc/rfc6742.html#section-2.4.1))
-- — an ILNP locator pointer: a 16-bit preference and a 'Domain'
-- naming a host that publishes locator records.
--
-- >  0                   1                   2                   3
-- >  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |          Preference           |                               /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               /
-- > /                                                               /
-- > /                              FQDN                             /
-- > /                                                               /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
-- The FQDN field is not subject to wire-form name compression.
-- The 'Eq' and 'Ord' instances compare the FQDN case-insensitively
-- in wire form (via 'equalWireHost' / 'compareWireHost').
--
-- See 'X_nid' and 'T_l32' for the rest of the ILNP record family.
data T_lp = T_LP
    { T_lp -> Word16
lpPref :: Word16
    , T_lp -> Domain
lpFqdn :: Domain
    } deriving (Int -> T_lp -> ShowS
[T_lp] -> ShowS
T_lp -> String
(Int -> T_lp -> ShowS)
-> (T_lp -> String) -> ([T_lp] -> ShowS) -> Show T_lp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_lp -> ShowS
showsPrec :: Int -> T_lp -> ShowS
$cshow :: T_lp -> String
show :: T_lp -> String
$cshowList :: [T_lp] -> ShowS
showList :: [T_lp] -> ShowS
Show)

-- | Case-insensitive wire-form equality.
instance Eq T_lp where
    T_lp
a == :: T_lp -> T_lp -> Bool
== T_lp
b = (T_lp -> Word16
lpPref T_lp
a) Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              (T_lp -> Word16
lpPref T_lp
b)
          Bool -> Bool -> Bool
&& (T_lp -> Domain
lpFqdn T_lp
a) Domain -> Domain -> Bool
`equalWireHost` (T_lp -> Domain
lpFqdn T_lp
b)

-- | Case-insensitive wire-form order.
instance Ord T_lp where
    compare :: T_lp -> T_lp -> Ordering
compare T_lp
a T_lp
b = (T_lp -> Word16
lpPref T_lp
a) Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         (T_lp -> Word16
lpPref T_lp
b)
               Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_lp -> Domain
lpFqdn T_lp
a) Domain -> Domain -> Ordering
`compareWireHost` (T_lp -> Domain
lpFqdn T_lp
b)

instance Presentable T_lp where
    present :: T_lp -> Builder -> Builder
present T_LP{Word16
Domain
lpPref :: T_lp -> Word16
lpFqdn :: T_lp -> Domain
lpPref :: Word16
lpFqdn :: Domain
..} = Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
lpPref (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Domain
lpFqdn

instance KnownRData T_lp where
    rdType :: forall b -> (b ~ T_lp) => RRTYPE
rdType _ = RRTYPE
LP
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_lp -> SPut s RData
rdEncode T_LP{Word16
Domain
lpPref :: T_lp -> Word16
lpFqdn :: T_lp -> Domain
lpPref :: Word16
lpFqdn :: Domain
..} = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData) -> SizedBuilder -> SPut s RData
forall a b. (a -> b) -> a -> b
$
        Word16 -> SizedBuilder
mbWord16 Word16
lpPref
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
lpFqdn
    rdDecode :: forall b ->
(b ~ T_lp) => RDataExtensionVal T_lp -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_lp
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        lpPref <- SGet Word16
get16
        lpFqdn <- getDomainNC
        pure $ RData $ T_LP{..}

-- | The @AMTRELAY@ resource record
-- ([RFC 8777 section 4](https://datatracker.ietf.org/doc/html/rfc8777#section-4))
-- — the relay-address for AMT (Automatic Multicast Tunneling)
-- discovery.  An 8-bit /precedence/, a 1-bit /discovery-optional/
-- flag, a 7-bit relay-type field, and an 'AmtRelay' value whose
-- format depends on the type:
--
-- > 0       empty
-- > 1       wire-form IPv4 address
-- > 2       wire-form IPv6 address
-- > 3       uncompressed wire-form domain name
-- > 4-127   reserved (unlikely to be specified)
--
-- >   0                   1                   2                   3
-- >   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-- >  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- >  |   precedence  |D|    type     |                               |
-- >  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-- >  ~                            relay                              ~
-- >  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
-- Derived 'Ord' compares precedence, then discovery flag, then
-- 'AmtRelay' (constructor order, then field), matching the
-- canonical wire-form ordering.  The 'Domain' inside an
-- @Amt_Host@ relay is compared case-sensitively, as is the
-- convention for RR types defined after RFC 4034.
data T_amtrelay = T_AMTRELAY
    { T_amtrelay -> Word8
amtPref  :: Word8 -- ^ Preference, lower is better
    , T_amtrelay -> Bool
amtDisc  :: Bool  -- ^ Discovery optional
    , T_amtrelay -> AmtRelay
amtRelay :: AmtRelay
    } deriving (T_amtrelay -> T_amtrelay -> Bool
(T_amtrelay -> T_amtrelay -> Bool)
-> (T_amtrelay -> T_amtrelay -> Bool) -> Eq T_amtrelay
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_amtrelay -> T_amtrelay -> Bool
== :: T_amtrelay -> T_amtrelay -> Bool
$c/= :: T_amtrelay -> T_amtrelay -> Bool
/= :: T_amtrelay -> T_amtrelay -> Bool
Eq, Eq T_amtrelay
Eq T_amtrelay =>
(T_amtrelay -> T_amtrelay -> Ordering)
-> (T_amtrelay -> T_amtrelay -> Bool)
-> (T_amtrelay -> T_amtrelay -> Bool)
-> (T_amtrelay -> T_amtrelay -> Bool)
-> (T_amtrelay -> T_amtrelay -> Bool)
-> (T_amtrelay -> T_amtrelay -> T_amtrelay)
-> (T_amtrelay -> T_amtrelay -> T_amtrelay)
-> Ord T_amtrelay
T_amtrelay -> T_amtrelay -> Bool
T_amtrelay -> T_amtrelay -> Ordering
T_amtrelay -> T_amtrelay -> T_amtrelay
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 :: T_amtrelay -> T_amtrelay -> Ordering
compare :: T_amtrelay -> T_amtrelay -> Ordering
$c< :: T_amtrelay -> T_amtrelay -> Bool
< :: T_amtrelay -> T_amtrelay -> Bool
$c<= :: T_amtrelay -> T_amtrelay -> Bool
<= :: T_amtrelay -> T_amtrelay -> Bool
$c> :: T_amtrelay -> T_amtrelay -> Bool
> :: T_amtrelay -> T_amtrelay -> Bool
$c>= :: T_amtrelay -> T_amtrelay -> Bool
>= :: T_amtrelay -> T_amtrelay -> Bool
$cmax :: T_amtrelay -> T_amtrelay -> T_amtrelay
max :: T_amtrelay -> T_amtrelay -> T_amtrelay
$cmin :: T_amtrelay -> T_amtrelay -> T_amtrelay
min :: T_amtrelay -> T_amtrelay -> T_amtrelay
Ord, Int -> T_amtrelay -> ShowS
[T_amtrelay] -> ShowS
T_amtrelay -> String
(Int -> T_amtrelay -> ShowS)
-> (T_amtrelay -> String)
-> ([T_amtrelay] -> ShowS)
-> Show T_amtrelay
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_amtrelay -> ShowS
showsPrec :: Int -> T_amtrelay -> ShowS
$cshow :: T_amtrelay -> String
show :: T_amtrelay -> String
$cshowList :: [T_amtrelay] -> ShowS
showList :: [T_amtrelay] -> ShowS
Show)

-- | New variants of the AmtRelay value type are not expected, so an ADT is
-- used to capture just the specified variants and an opaque catchall.
--
data AmtRelay = Amt_Nil
              | Amt_A IPv4
              | Amt_AAAA IPv6
              | Amt_Host Host
              | Amt_Any_ Word8 ShortByteString
  deriving (AmtRelay -> AmtRelay -> Bool
(AmtRelay -> AmtRelay -> Bool)
-> (AmtRelay -> AmtRelay -> Bool) -> Eq AmtRelay
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AmtRelay -> AmtRelay -> Bool
== :: AmtRelay -> AmtRelay -> Bool
$c/= :: AmtRelay -> AmtRelay -> Bool
/= :: AmtRelay -> AmtRelay -> Bool
Eq, Eq AmtRelay
Eq AmtRelay =>
(AmtRelay -> AmtRelay -> Ordering)
-> (AmtRelay -> AmtRelay -> Bool)
-> (AmtRelay -> AmtRelay -> Bool)
-> (AmtRelay -> AmtRelay -> Bool)
-> (AmtRelay -> AmtRelay -> Bool)
-> (AmtRelay -> AmtRelay -> AmtRelay)
-> (AmtRelay -> AmtRelay -> AmtRelay)
-> Ord AmtRelay
AmtRelay -> AmtRelay -> Bool
AmtRelay -> AmtRelay -> Ordering
AmtRelay -> AmtRelay -> AmtRelay
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 :: AmtRelay -> AmtRelay -> Ordering
compare :: AmtRelay -> AmtRelay -> Ordering
$c< :: AmtRelay -> AmtRelay -> Bool
< :: AmtRelay -> AmtRelay -> Bool
$c<= :: AmtRelay -> AmtRelay -> Bool
<= :: AmtRelay -> AmtRelay -> Bool
$c> :: AmtRelay -> AmtRelay -> Bool
> :: AmtRelay -> AmtRelay -> Bool
$c>= :: AmtRelay -> AmtRelay -> Bool
>= :: AmtRelay -> AmtRelay -> Bool
$cmax :: AmtRelay -> AmtRelay -> AmtRelay
max :: AmtRelay -> AmtRelay -> AmtRelay
$cmin :: AmtRelay -> AmtRelay -> AmtRelay
min :: AmtRelay -> AmtRelay -> AmtRelay
Ord, Int -> AmtRelay -> ShowS
[AmtRelay] -> ShowS
AmtRelay -> String
(Int -> AmtRelay -> ShowS)
-> (AmtRelay -> String) -> ([AmtRelay] -> ShowS) -> Show AmtRelay
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AmtRelay -> ShowS
showsPrec :: Int -> AmtRelay -> ShowS
$cshow :: AmtRelay -> String
show :: AmtRelay -> String
$cshowList :: [AmtRelay] -> ShowS
showList :: [AmtRelay] -> ShowS
Show)

-- | /Smart constructor/ of opaque relay forms, that ensures a non-empty value
-- and type in [4,127].  The underlying @Amt_Any_@ constructor is not exposed.
--
pattern Amt_Opaque :: Word8 -> ShortByteString -> AmtRelay
pattern $mAmt_Opaque :: forall {r}.
AmtRelay -> (Word8 -> ShortByteString -> r) -> ((# #) -> r) -> r
$bAmt_Opaque :: Word8 -> ShortByteString -> AmtRelay
Amt_Opaque t b <- Amt_Any_ t b where
    Amt_Opaque Word8
t ShortByteString
b | Word8
t Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
3 Bool -> Bool -> Bool
&& Word8
t Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
128 Bool -> Bool -> Bool
&& Bool -> Bool
not (ShortByteString -> Bool
SB.null ShortByteString
b) = Word8 -> ShortByteString -> AmtRelay
Amt_Any_ Word8
t ShortByteString
b
                   | Bool
otherwise = String -> AmtRelay
forall a. HasCallStack => String -> a
error String
"Invalid opaque AmtRelay"

amtTypeWord :: Bool -> Word8 -> Word8
amtTypeWord :: Bool -> Word8 -> Word8
amtTypeWord Bool
d Word8
t = Word8 -> Word8 -> Bool -> Word8
forall a. a -> a -> Bool -> a
bool Word8
t (Word8
0x80 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
t) Bool
d

instance Presentable T_amtrelay where
    present :: T_amtrelay -> Builder -> Builder
present T_AMTRELAY{Bool
Word8
AmtRelay
amtPref :: T_amtrelay -> Word8
amtDisc :: T_amtrelay -> Bool
amtRelay :: T_amtrelay -> AmtRelay
amtPref :: Word8
amtDisc :: Bool
amtRelay :: AmtRelay
..} = case AmtRelay
amtRelay of
        AmtRelay
Amt_Nil -> Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word8
amtPref
                   (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp (Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
amtDisc)
                   (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @Word8 Word8
0
                   (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp String
"."
        Amt_A IPv4
a -> Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word8
amtPref
                   (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp (Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
amtDisc)
                   (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @Word8 Word8
1
                   (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IPv4 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp IPv4
a
        Amt_AAAA IPv6
a -> Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word8
amtPref
                      (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp (Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
amtDisc)
                      (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @Word8 Word8
2
                      (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IPv6 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp IPv6
a
        Amt_Host Host
h -> Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word8
amtPref
                      (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp (Bool -> Int
forall a. Enum a => a -> Int
fromEnum Bool
amtDisc)
                      (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
presentSp @Word8 Word8
3
                      (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp (Host -> Domain
fromHost Host
h)
        Amt_Any_ Word8
t ShortByteString
bs ->
            String -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present String
"\\# "
            (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ShortByteString -> Int
SB.length ShortByteString
bs)
            (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Char
' '
            (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Builder
word8HexFixed Word8
amtPref Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>)
            (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Builder
word8HexFixed (Bool -> Word8 -> Word8
amtTypeWord Bool
amtDisc Word8
t) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>)
            (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => a -> Builder -> Builder
present @Bytes16 (ShortByteString -> Bytes16
forall a b. Coercible a b => a -> b
coerce ShortByteString
bs)

instance KnownRData T_amtrelay where
    rdType :: forall b -> (b ~ T_amtrelay) => RRTYPE
rdType _ = RRTYPE
AMTRELAY
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_amtrelay -> SPut s RData
rdEncode T_AMTRELAY{Bool
Word8
AmtRelay
amtPref :: T_amtrelay -> Word8
amtDisc :: T_amtrelay -> Bool
amtRelay :: T_amtrelay -> AmtRelay
amtPref :: Word8
amtDisc :: Bool
amtRelay :: AmtRelay
..} = do
        Word8 -> SPut s RData
forall r s. ErrorContext r => Word8 -> SPut s r
put8 Word8
amtPref
        case AmtRelay
amtRelay of
            AmtRelay
Amt_Nil -> Word8 -> SPut s RData
forall r s. ErrorContext r => Word8 -> SPut s r
put8 (Bool -> Word8 -> Word8
amtTypeWord Bool
amtDisc Word8
0)
            Amt_A IPv4
a -> do
                Word8 -> SPut s RData
forall r s. ErrorContext r => Word8 -> SPut s r
put8 (Bool -> Word8 -> Word8
amtTypeWord Bool
amtDisc Word8
1)
                IPv4 -> SPut s RData
forall r s. ErrorContext r => IPv4 -> SPut s r
putIPv4 IPv4
a
            Amt_AAAA IPv6
a -> do
                Word8 -> SPut s RData
forall r s. ErrorContext r => Word8 -> SPut s r
put8 (Bool -> Word8 -> Word8
amtTypeWord Bool
amtDisc Word8
2)
                IPv6 -> SPut s RData
forall r s. ErrorContext r => IPv6 -> SPut s r
putIPv6 IPv6
a
            Amt_Host Host
h -> do
                Word8 -> SPut s RData
forall r s. ErrorContext r => Word8 -> SPut s r
put8 (Bool -> Word8 -> Word8
amtTypeWord Bool
amtDisc Word8
3)
                Domain -> SPut s RData
forall r s. ErrorContext r => Domain -> SPut s r
putWireForm (Host -> Domain
fromHost Host
h)
            Amt_Any_ Word8
t ShortByteString
bs -> do
                Word8 -> SPut s RData
forall r s. ErrorContext r => Word8 -> SPut s r
put8 (Bool -> Word8 -> Word8
amtTypeWord Bool
amtDisc Word8
t)
                ShortByteString -> SPut s RData
forall r s. ErrorContext r => ShortByteString -> SPut s r
putShortByteString ShortByteString
bs
    rdDecode :: forall b ->
(b ~ T_amtrelay) =>
RDataExtensionVal T_amtrelay -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_amtrelay
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        amtPref <- SGet Word8
get8
        w <- get8
        let amtDisc = (Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x80) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
0
            t = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x7f
        amtRelay <- case t of
            Word8
0 -> AmtRelay -> SGet AmtRelay
forall a. a -> SGet a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AmtRelay
Amt_Nil
            Word8
1 -> IPv4 -> AmtRelay
Amt_A (IPv4 -> AmtRelay) -> SGet IPv4 -> SGet AmtRelay
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet IPv4
getIPv4
            Word8
2 -> IPv6 -> AmtRelay
Amt_AAAA (IPv6 -> AmtRelay) -> SGet IPv6 -> SGet AmtRelay
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet IPv6
getIPv6
            Word8
3 -> Host -> AmtRelay
Amt_Host (Host -> AmtRelay) -> (Domain -> Host) -> Domain -> AmtRelay
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> Host
toHost (Domain -> AmtRelay) -> SGet Domain -> SGet AmtRelay
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet Domain
getDomain
            Word8
_ -> Word8 -> ShortByteString -> AmtRelay
Amt_Any_ Word8
t (ShortByteString -> AmtRelay)
-> SGet ShortByteString -> SGet AmtRelay
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet ShortByteString
getShortByteString
        pure $ RData $ T_AMTRELAY{..}