{-|
Module      : Net.DNSBase.RData.Obsolete
Description : Obsolete RR types retained for wire-form parsing
Copyright   : (c) Viktor Dukhovni, 2026
License     : BSD-3-Clause
Maintainer  : ietf-dane@dukhovni.org
Stability   : unstable

A grab-bag of RR types that are no longer used in current zone
data but appear in historic records and zone-data archives.
They are defined here so wire-form parsers can read stray
examples without failing.  No new deployment should use any of
these types.

The module gathers four loose groups:

* Early host-name and mailbox pointers: 'T_md', 'T_mf', 'T_mb',
  'T_mg', 'T_mr' (the shared codec 'X_domain' is re-exported
  here).
* RFC 1035 and RFC 1183 records that never saw wide use:
  'T_minfo', 'T_x25', 'T_isdn', 'T_rt'.
* OSI / X.400-mapping records, all deprecated by RFC 9121:
  'T_nsap', 'T_nsapptr', 'T_px'.
* Other one-offs: 'T_gpos' (early geographic location,
  superseded by 'LOC'), 'T_kx' (Key Exchange), 'T_a6'
  (chained IPv6 addressing; obsoleted by RFC 6563).

'T_wks' (Well-Known Services) is re-exported here for
convenience; its definition lives in "Net.DNSBase.RData.WKS".

The pre-RFC-4034 records in this module lower-case their
embedded domains in canonical form; 'T_nsapptr' is the
exception (its derived instances compare the wire bytes
case-sensitively).
-}
{-# LANGUAGE RecordWildCards #-}

module Net.DNSBase.RData.Obsolete
    ( -- * Obsolete RR types
      -- ** Obsolete RR types representing a host name or mailbox.
      X_domain(T_MD, T_MF, T_MB, T_MG, T_MR)
    , T_md
    , T_mf
    , T_mb
    , T_mg
    , T_mr
      -- ** Other obsolete RR types.
    , T_wks(..)
    , WksProto(..)
    , T_minfo(..)
    , T_x25(..)
    , T_isdn(..)
    , T_rt(..)
    , T_nsap(..)
    , T_nsapptr(..)
    , T_px(..)
    , T_gpos(..)
    , T_kx(..)
    , T_a6(T_A6)
    ) where

import qualified Data.ByteString.Short as SB
import Net.DNSBase.Internal.Util
import Net.DNSBase.RData.Internal.XNAME

import Net.DNSBase.Bytes
import Net.DNSBase.Decode.Domain
import Net.DNSBase.Decode.State
import Net.DNSBase.Domain
import Net.DNSBase.Encode.State
import Net.DNSBase.Present
import Net.DNSBase.RData
import Net.DNSBase.RData.WKS
import Net.DNSBase.RRTYPE
import Net.DNSBase.Text

-- | The @MINFO@ resource record
-- ([RFC 1035 section 3.3.7](https://datatracker.ietf.org/doc/html/rfc1035#section-3.3.7))
-- — mailing-list request and owner addresses: two 'Domain'
-- fields, the request mailbox and the owner (bounce) mailbox.
--
-- >  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- >  /                    RMAILBX                    /
-- >  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- >  /                    EMAILBX                    /
-- >  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
--
-- Both fields are subject to wire-form name compression on encode
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4))
-- and canonicalise to lower case
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
-- The 'Eq' and 'Ord' instances compare both domain fields in
-- canonical wire form (via 'equalWireHost' / 'compareWireHost'),
-- so 'Ord' is canonical.
data T_minfo = T_MINFO
    { T_minfo -> Domain
minfoRmailbx :: Domain -- ^ Request address
    , T_minfo -> Domain
minfoEmailbx :: Domain -- ^ Owner (bounce) address
    } deriving (Int -> T_minfo -> ShowS
[T_minfo] -> ShowS
T_minfo -> String
(Int -> T_minfo -> ShowS)
-> (T_minfo -> String) -> ([T_minfo] -> ShowS) -> Show T_minfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_minfo -> ShowS
showsPrec :: Int -> T_minfo -> ShowS
$cshow :: T_minfo -> String
show :: T_minfo -> String
$cshowList :: [T_minfo] -> ShowS
showList :: [T_minfo] -> ShowS
Show)

-- | Case-insensitive wire-form equality.
instance Eq T_minfo where
    T_minfo
a == :: T_minfo -> T_minfo -> Bool
== T_minfo
b = (T_minfo -> Domain
minfoRmailbx T_minfo
a) Domain -> Domain -> Bool
`equalWireHost` (T_minfo -> Domain
minfoRmailbx T_minfo
b)
          Bool -> Bool -> Bool
&& (T_minfo -> Domain
minfoEmailbx T_minfo
a) Domain -> Domain -> Bool
`equalWireHost` (T_minfo -> Domain
minfoEmailbx T_minfo
b)

-- | Case-insensitive wire-form order.
instance Ord T_minfo where
    T_minfo
a compare :: T_minfo -> T_minfo -> Ordering
`compare` T_minfo
b = (T_minfo -> Domain
minfoRmailbx T_minfo
a) Domain -> Domain -> Ordering
`compareWireHost` (T_minfo -> Domain
minfoRmailbx T_minfo
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_minfo -> Domain
minfoEmailbx T_minfo
a) Domain -> Domain -> Ordering
`compareWireHost` (T_minfo -> Domain
minfoEmailbx T_minfo
b)

instance Presentable T_minfo where
    present :: T_minfo -> Builder -> Builder
present T_MINFO{Domain
minfoRmailbx :: T_minfo -> Domain
minfoEmailbx :: T_minfo -> Domain
minfoRmailbx :: Domain
minfoEmailbx :: Domain
..} =
        Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Domain
minfoRmailbx
        (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
minfoEmailbx

instance KnownRData T_minfo where
    rdType :: forall b -> (b ~ T_minfo) => RRTYPE
rdType _ = RRTYPE
MINFO
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_minfo -> SPut s RData
rdEncode T_MINFO{Domain
minfoRmailbx :: T_minfo -> Domain
minfoEmailbx :: T_minfo -> Domain
minfoRmailbx :: Domain
minfoEmailbx :: Domain
..} = do
        -- Subject to name compression.
        Domain -> SPut s RData
forall r s. ErrorContext r => Domain -> SPut s r
putDomain Domain
minfoRmailbx
        Domain -> SPut s RData
forall r s. ErrorContext r => Domain -> SPut s r
putDomain Domain
minfoEmailbx
    cnEncode :: forall s. T_minfo -> SPut s RData
cnEncode T_MINFO{Domain
minfoRmailbx :: T_minfo -> Domain
minfoEmailbx :: T_minfo -> Domain
minfoRmailbx :: Domain
minfoEmailbx :: 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
$
           Domain -> SizedBuilder
mbWireForm (Domain -> Domain
canonicalise Domain
minfoRmailbx)
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm (Domain -> Domain
canonicalise Domain
minfoEmailbx)
    rdDecode :: forall b ->
(b ~ T_minfo) => RDataExtensionVal T_minfo -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_minfo
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        -- Subject to name compression.
        minfoRmailbx <- SGet Domain
getDomain
        minfoEmailbx <- getDomain
        return $ RData $ T_MINFO{..}

-- | The @X25@ resource record
-- ([RFC 1183 section 3.1](https://www.rfc-editor.org/rfc/rfc1183.html#section-3.1))
-- — an X.25 PSDN address held as a single DNS
-- /character-string/.  RFC 1183 calls for at least four ASCII
-- digits, but the constructor does not enforce that — callers may
-- store any byte sequence that fits in a character-string (up to
-- 255 bytes).
--
-- The 'Ord' instance compares the payload as a DNS
-- character-string (length-prefixed lexicographic), so it agrees
-- with the canonical wire-form ordering of
-- [RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2).
newtype T_x25 = T_X25 SB.ShortByteString
    deriving (T_x25 -> T_x25 -> Bool
(T_x25 -> T_x25 -> Bool) -> (T_x25 -> T_x25 -> Bool) -> Eq T_x25
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_x25 -> T_x25 -> Bool
== :: T_x25 -> T_x25 -> Bool
$c/= :: T_x25 -> T_x25 -> Bool
/= :: T_x25 -> T_x25 -> Bool
Eq, Int -> T_x25 -> ShowS
[T_x25] -> ShowS
T_x25 -> String
(Int -> T_x25 -> ShowS)
-> (T_x25 -> String) -> ([T_x25] -> ShowS) -> Show T_x25
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_x25 -> ShowS
showsPrec :: Int -> T_x25 -> ShowS
$cshow :: T_x25 -> String
show :: T_x25 -> String
$cshowList :: [T_x25] -> ShowS
showList :: [T_x25] -> ShowS
Show)

instance Ord T_x25 where
    (T_X25 ShortByteString
a) compare :: T_x25 -> T_x25 -> Ordering
`compare` (T_X25 ShortByteString
b) = (ShortByteString -> DnsText)
-> ShortByteString -> ShortByteString -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing ShortByteString -> DnsText
DnsText ShortByteString
a ShortByteString
b

instance Presentable T_x25 where
    present :: T_x25 -> Builder -> Builder
present (T_X25 ShortByteString
str) = forall a. Presentable a => a -> Builder -> Builder
present @DnsText (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
str)

instance KnownRData T_x25 where
    rdType :: forall b -> (b ~ T_x25) => RRTYPE
rdType _ = RRTYPE
X25
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_x25 -> SPut s RData
rdEncode = ShortByteString -> SPut s RData
forall r s. ErrorContext r => ShortByteString -> SPut s r
putShortByteStringLen8 (ShortByteString -> SPut s RData)
-> (T_x25 -> ShortByteString) -> T_x25 -> SPut s RData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T_x25 -> ShortByteString
forall a b. Coercible a b => a -> b
coerce
    rdDecode :: forall b ->
(b ~ T_x25) => RDataExtensionVal T_x25 -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_x25
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const (SGet RData -> Int -> SGet RData)
-> SGet RData -> Int -> SGet RData
forall a b. (a -> b) -> a -> b
$ T_x25 -> RData
forall a. KnownRData a => a -> RData
RData (T_x25 -> RData)
-> (ShortByteString -> T_x25) -> ShortByteString -> RData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> T_x25
T_X25 (ShortByteString -> RData) -> SGet ShortByteString -> SGet RData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet ShortByteString
getShortByteStringLen8

-- | The @ISDN@ resource record
-- ([RFC 1183 section 3.2](https://www.rfc-editor.org/rfc/rfc1183.html#section-3.2))
-- — the ISDN number of the owner host, with an optional
-- Direct-Dial-In subaddress.  Both fields are DNS
-- /character-strings/; only the address is mandatory.
--
-- The 'Ord' instance compares both fields as DNS
-- character-strings.  With the trailing DDI absent, the wire form
-- is shorter than any encoding with a present DDI, so 'Ord' agrees
-- with the canonical wire-form ordering of
-- [RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2).
data T_isdn = T_ISDN SB.ShortByteString (Maybe SB.ShortByteString)
    deriving (T_isdn -> T_isdn -> Bool
(T_isdn -> T_isdn -> Bool)
-> (T_isdn -> T_isdn -> Bool) -> Eq T_isdn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_isdn -> T_isdn -> Bool
== :: T_isdn -> T_isdn -> Bool
$c/= :: T_isdn -> T_isdn -> Bool
/= :: T_isdn -> T_isdn -> Bool
Eq, Int -> T_isdn -> ShowS
[T_isdn] -> ShowS
T_isdn -> String
(Int -> T_isdn -> ShowS)
-> (T_isdn -> String) -> ([T_isdn] -> ShowS) -> Show T_isdn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_isdn -> ShowS
showsPrec :: Int -> T_isdn -> ShowS
$cshow :: T_isdn -> String
show :: T_isdn -> String
$cshowList :: [T_isdn] -> ShowS
showList :: [T_isdn] -> ShowS
Show)

instance Ord T_isdn where
    (T_ISDN ShortByteString
aa Maybe ShortByteString
ad) compare :: T_isdn -> T_isdn -> Ordering
`compare` (T_ISDN ShortByteString
ba Maybe ShortByteString
bd) = ShortByteString
aa ShortByteString -> ShortByteString -> Ordering
`strCompare`  ShortByteString
ba
                                           Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Maybe ShortByteString
ad Maybe ShortByteString -> Maybe ShortByteString -> Ordering
`mstrCompare` Maybe ShortByteString
bd
      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
        mstrCompare :: Maybe ShortByteString -> Maybe ShortByteString -> Ordering
mstrCompare = (Maybe ShortByteString -> Maybe DnsText)
-> Maybe ShortByteString -> Maybe ShortByteString -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing ((ShortByteString -> DnsText)
-> Maybe ShortByteString -> Maybe DnsText
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ShortByteString -> DnsText
DnsText)

instance Presentable T_isdn where
    present :: T_isdn -> Builder -> Builder
present (T_ISDN ShortByteString
address Maybe ShortByteString
ddi) =
        forall a. Presentable a => a -> Builder -> Builder
present @DnsText (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
address)
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> Builder)
-> (ShortByteString -> Builder -> Builder)
-> Maybe ShortByteString
-> Builder
-> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder -> Builder
forall a. a -> a
id (forall a. Presentable a => a -> Builder -> Builder
presentSp @DnsText (DnsText -> Builder -> Builder)
-> (ShortByteString -> DnsText)
-> ShortByteString
-> Builder
-> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce) Maybe ShortByteString
ddi

instance KnownRData T_isdn where
    rdType :: forall b -> (b ~ T_isdn) => RRTYPE
rdType _ = RRTYPE
ISDN
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_isdn -> SPut s RData
rdEncode (T_ISDN ShortByteString
address Maybe ShortByteString
ddi) = do
        ShortByteString -> SPut s RData
forall r s. ErrorContext r => ShortByteString -> SPut s r
putShortByteStringLen8 ShortByteString
address
        (ShortByteString -> SPut s RData)
-> Maybe ShortByteString -> SPut s RData
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ShortByteString -> SPut s RData
forall r s. ErrorContext r => ShortByteString -> SPut s r
putShortByteStringLen8 Maybe ShortByteString
ddi
    rdDecode :: forall b ->
(b ~ T_isdn) => RDataExtensionVal T_isdn -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_isdn
_ Int
len = do
        pos0 <- SGet Int
getPosition
        address <- getShortByteStringLen8
        used <- subtract pos0 <$> getPosition
        ddi <- if | used == len -> pure Nothing
                  | otherwise   -> Just <$> getShortByteStringLen8
        pure $ RData $ T_ISDN address ddi

-- | The @RT@ resource record
-- ([RFC 1183 section 3.3](https://www.rfc-editor.org/rfc/rfc1183.html#section-3.3))
-- — Route-Through: a 16-bit preference and a 'Domain' naming an
-- intermediate host that will route packets to the owner.  Used
-- in the X.25 and ISDN era for hosts without their own wide-area
-- addresses.
--
-- The route-through domain is not subject to wire-form name
-- compression on encode but compression is tolerated on decode
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4)).
-- 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 domain in canonical
-- wire form (via 'equalWireHost' / 'compareWireHost'), so 'Ord'
-- is canonical.
data T_rt = T_RT Word16 Domain
    deriving (Int -> T_rt -> ShowS
[T_rt] -> ShowS
T_rt -> String
(Int -> T_rt -> ShowS)
-> (T_rt -> String) -> ([T_rt] -> ShowS) -> Show T_rt
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_rt -> ShowS
showsPrec :: Int -> T_rt -> ShowS
$cshow :: T_rt -> String
show :: T_rt -> String
$cshowList :: [T_rt] -> ShowS
showList :: [T_rt] -> ShowS
Show)

instance Eq T_rt where
    (T_RT Word16
pa Domain
ra) == :: T_rt -> T_rt -> Bool
== (T_RT Word16
pb Domain
rb) = Word16
pa Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
== Word16
pb Bool -> Bool -> Bool
&& Domain
ra Domain -> Domain -> Bool
`equalWireHost` Domain
rb

instance Ord T_rt where
    (T_RT Word16
pa Domain
ra) compare :: T_rt -> T_rt -> Ordering
`compare` (T_RT Word16
pb Domain
rb) =
        Word16
pa Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` Word16
pb
     Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Domain
ra Domain -> Domain -> Ordering
`compareWireHost` Domain
rb

instance Presentable T_rt where
    present :: T_rt -> Builder -> Builder
present (T_RT Word16
pref Domain
router) = Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
pref (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
router

instance KnownRData T_rt where
    rdType :: forall b -> (b ~ T_rt) => RRTYPE
rdType _ = RRTYPE
RT
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_rt -> SPut s RData
rdEncode (T_RT Word16
pref Domain
router) = 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
pref SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
router
    cnEncode :: forall s. T_rt -> SPut s RData
cnEncode (T_RT Word16
pref Domain
router) =
        T_rt -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_rt -> SPut s RData
rdEncode (T_rt -> SPut s RData) -> T_rt -> SPut s RData
forall a b. (a -> b) -> a -> b
$ Word16 -> Domain -> T_rt
T_RT Word16
pref (Domain -> Domain
canonicalise Domain
router)
    rdDecode :: forall b ->
(b ~ T_rt) => RDataExtensionVal T_rt -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_rt
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        pref <- SGet Word16
get16
        router <- getDomain
        pure $ RData $ T_RT pref router

-- | The @NSAP@ resource record
-- ([RFC 1706 section 5](https://www.rfc-editor.org/rfc/rfc1706.html#section-5);
-- deprecated by [RFC 9121](https://www.rfc-editor.org/rfc/rfc9121))
-- — mapped a domain name to an OSI Network Service Access Point
-- address.  An opaque byte string carrying the NSAP value
-- verbatim; presented in zone-file syntax as a @0x@-prefixed hex
-- literal.
--
-- Derived 'Ord' compares the raw bytes, which matches the
-- canonical wire-form ordering of
-- [RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2).
newtype T_nsap = T_NSAP SB.ShortByteString
    deriving (T_nsap -> T_nsap -> Bool
(T_nsap -> T_nsap -> Bool)
-> (T_nsap -> T_nsap -> Bool) -> Eq T_nsap
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_nsap -> T_nsap -> Bool
== :: T_nsap -> T_nsap -> Bool
$c/= :: T_nsap -> T_nsap -> Bool
/= :: T_nsap -> T_nsap -> Bool
Eq, Eq T_nsap
Eq T_nsap =>
(T_nsap -> T_nsap -> Ordering)
-> (T_nsap -> T_nsap -> Bool)
-> (T_nsap -> T_nsap -> Bool)
-> (T_nsap -> T_nsap -> Bool)
-> (T_nsap -> T_nsap -> Bool)
-> (T_nsap -> T_nsap -> T_nsap)
-> (T_nsap -> T_nsap -> T_nsap)
-> Ord T_nsap
T_nsap -> T_nsap -> Bool
T_nsap -> T_nsap -> Ordering
T_nsap -> T_nsap -> T_nsap
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_nsap -> T_nsap -> Ordering
compare :: T_nsap -> T_nsap -> Ordering
$c< :: T_nsap -> T_nsap -> Bool
< :: T_nsap -> T_nsap -> Bool
$c<= :: T_nsap -> T_nsap -> Bool
<= :: T_nsap -> T_nsap -> Bool
$c> :: T_nsap -> T_nsap -> Bool
> :: T_nsap -> T_nsap -> Bool
$c>= :: T_nsap -> T_nsap -> Bool
>= :: T_nsap -> T_nsap -> Bool
$cmax :: T_nsap -> T_nsap -> T_nsap
max :: T_nsap -> T_nsap -> T_nsap
$cmin :: T_nsap -> T_nsap -> T_nsap
min :: T_nsap -> T_nsap -> T_nsap
Ord)

instance Show T_nsap where
    showsPrec :: Int -> T_nsap -> ShowS
showsPrec Int
p T_nsap
a = String -> ShowS
showString String
"0x" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => Int -> a -> ShowS
showsPrec @Bytes16 Int
p (T_nsap -> Bytes16
forall a b. Coercible a b => a -> b
coerce T_nsap
a)

instance Presentable T_nsap where
    present :: T_nsap -> Builder -> Builder
present T_nsap
a = forall a. Presentable a => a -> Builder -> Builder
present @String String
"0x" (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 (T_nsap -> Bytes16
forall a b. Coercible a b => a -> b
coerce T_nsap
a)

instance KnownRData T_nsap where
    rdType :: forall b -> (b ~ T_nsap) => RRTYPE
rdType _ = RRTYPE
NSAP
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_nsap -> SPut s RData
rdEncode = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData)
-> (T_nsap -> SizedBuilder) -> T_nsap -> SPut s RData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> SizedBuilder
mbShortByteString (ShortByteString -> SizedBuilder)
-> (T_nsap -> ShortByteString) -> T_nsap -> SizedBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T_nsap -> ShortByteString
forall a b. Coercible a b => a -> b
coerce
    rdDecode :: forall b ->
(b ~ T_nsap) => RDataExtensionVal T_nsap -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_nsap
_ = T_nsap -> RData
forall a. KnownRData a => a -> RData
RData (T_nsap -> RData)
-> (ShortByteString -> T_nsap) -> ShortByteString -> RData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> T_nsap
T_NSAP (ShortByteString -> RData)
-> (Int -> SGet ShortByteString) -> Int -> SGet RData
forall (m :: * -> *) b c a.
Functor m =>
(b -> c) -> (a -> m b) -> a -> m c
<.> Int -> SGet ShortByteString
getShortNByteString

-- | The @NSAPPTR@ resource record
-- ([RFC 1348](https://www.rfc-editor.org/rfc/rfc1348#page-2);
-- obsoleted by @PTR@ in
-- [RFC 1706 section 6](https://www.rfc-editor.org/rfc/rfc1706.html#section-6),
-- deprecated by [RFC 9121](https://www.rfc-editor.org/rfc/rfc9121))
-- — the OSI counterpart of @PTR@, mapping an NSAP-derived owner
-- name to a domain name.
--
-- The target domain is not subject to wire-form name compression
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4))
-- and is /not/ in the
-- [RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)
-- list of types that lower-case their RDATA names.  Derived 'Eq'
-- and 'Ord' therefore compare the wire bytes verbatim
-- (case-sensitively).
newtype T_nsapptr = T_NSAPPTR Domain -- ^ Target 'Domain'
    deriving (T_nsapptr -> T_nsapptr -> Bool
(T_nsapptr -> T_nsapptr -> Bool)
-> (T_nsapptr -> T_nsapptr -> Bool) -> Eq T_nsapptr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_nsapptr -> T_nsapptr -> Bool
== :: T_nsapptr -> T_nsapptr -> Bool
$c/= :: T_nsapptr -> T_nsapptr -> Bool
/= :: T_nsapptr -> T_nsapptr -> Bool
Eq, Eq T_nsapptr
Eq T_nsapptr =>
(T_nsapptr -> T_nsapptr -> Ordering)
-> (T_nsapptr -> T_nsapptr -> Bool)
-> (T_nsapptr -> T_nsapptr -> Bool)
-> (T_nsapptr -> T_nsapptr -> Bool)
-> (T_nsapptr -> T_nsapptr -> Bool)
-> (T_nsapptr -> T_nsapptr -> T_nsapptr)
-> (T_nsapptr -> T_nsapptr -> T_nsapptr)
-> Ord T_nsapptr
T_nsapptr -> T_nsapptr -> Bool
T_nsapptr -> T_nsapptr -> Ordering
T_nsapptr -> T_nsapptr -> T_nsapptr
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_nsapptr -> T_nsapptr -> Ordering
compare :: T_nsapptr -> T_nsapptr -> Ordering
$c< :: T_nsapptr -> T_nsapptr -> Bool
< :: T_nsapptr -> T_nsapptr -> Bool
$c<= :: T_nsapptr -> T_nsapptr -> Bool
<= :: T_nsapptr -> T_nsapptr -> Bool
$c> :: T_nsapptr -> T_nsapptr -> Bool
> :: T_nsapptr -> T_nsapptr -> Bool
$c>= :: T_nsapptr -> T_nsapptr -> Bool
>= :: T_nsapptr -> T_nsapptr -> Bool
$cmax :: T_nsapptr -> T_nsapptr -> T_nsapptr
max :: T_nsapptr -> T_nsapptr -> T_nsapptr
$cmin :: T_nsapptr -> T_nsapptr -> T_nsapptr
min :: T_nsapptr -> T_nsapptr -> T_nsapptr
Ord, Int -> T_nsapptr -> ShowS
[T_nsapptr] -> ShowS
T_nsapptr -> String
(Int -> T_nsapptr -> ShowS)
-> (T_nsapptr -> String)
-> ([T_nsapptr] -> ShowS)
-> Show T_nsapptr
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_nsapptr -> ShowS
showsPrec :: Int -> T_nsapptr -> ShowS
$cshow :: T_nsapptr -> String
show :: T_nsapptr -> String
$cshowList :: [T_nsapptr] -> ShowS
showList :: [T_nsapptr] -> ShowS
Show)

instance Presentable T_nsapptr where
    present :: T_nsapptr -> Builder -> Builder
present = forall a. Presentable a => a -> Builder -> Builder
present @Domain (Domain -> Builder -> Builder)
-> (T_nsapptr -> Domain) -> T_nsapptr -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T_nsapptr -> Domain
forall a b. Coercible a b => a -> b
coerce

instance KnownRData T_nsapptr where
    rdType :: forall b -> (b ~ T_nsapptr) => RRTYPE
rdType _ = RRTYPE
NSAPPTR
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_nsapptr -> SPut s RData
rdEncode = SizedBuilder -> SPut s RData
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s RData)
-> (T_nsapptr -> SizedBuilder) -> T_nsapptr -> SPut s RData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> SizedBuilder
mbWireForm (Domain -> SizedBuilder)
-> (T_nsapptr -> Domain) -> T_nsapptr -> SizedBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T_nsapptr -> Domain
forall a b. Coercible a b => a -> b
coerce
    rdDecode :: forall b ->
(b ~ T_nsapptr) => RDataExtensionVal T_nsapptr -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_nsapptr
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        T_nsapptr -> RData
forall a. KnownRData a => a -> RData
RData (T_nsapptr -> RData) -> (Domain -> T_nsapptr) -> Domain -> RData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> T_nsapptr
T_NSAPPTR (Domain -> RData) -> SGet Domain -> SGet RData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet Domain
getDomainNC

-- | The @PX@ resource record
-- ([RFC 2163 section 4](https://www.rfc-editor.org/rfc/rfc2163.html#section-4);
-- deprecated by [RFC 9121](https://www.rfc-editor.org/rfc/rfc9121))
-- — points at X.400/RFC 822 mapping information: a 16-bit
-- preference and two 'Domain' fields naming the RFC 822 (SMTP)
-- and X.400 sides of the mapping.
--
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > |                  PREFERENCE                   |
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                    MAP822                     /
-- > /                                               /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                    MAPX400                    /
-- > /                                               /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
--
-- Neither domain field is subject to wire-form name compression
-- on encode but compression is tolerated on decode
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4)).
-- Both canonicalise to lower case
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
-- The 'Eq' and 'Ord' instances compare both domains in canonical
-- wire form (via 'equalWireHost' / 'compareWireHost'), so 'Ord'
-- is canonical.
data T_px = T_PX
    { T_px -> Word16
pxPref    :: Word16
    , T_px -> Domain
pxMap822  :: Domain
    , T_px -> Domain
pxMapX400 :: Domain
    } deriving (Int -> T_px -> ShowS
[T_px] -> ShowS
T_px -> String
(Int -> T_px -> ShowS)
-> (T_px -> String) -> ([T_px] -> ShowS) -> Show T_px
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_px -> ShowS
showsPrec :: Int -> T_px -> ShowS
$cshow :: T_px -> String
show :: T_px -> String
$cshowList :: [T_px] -> ShowS
showList :: [T_px] -> ShowS
Show)

instance Eq T_px where
    T_px
a == :: T_px -> T_px -> Bool
== T_px
b = T_px -> Word16
pxPref    T_px
a Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              T_px -> Word16
pxPref    T_px
b
          Bool -> Bool -> Bool
&& T_px -> Domain
pxMap822  T_px
a Domain -> Domain -> Bool
`equalWireHost` T_px -> Domain
pxMap822  T_px
b
          Bool -> Bool -> Bool
&& T_px -> Domain
pxMapX400 T_px
a Domain -> Domain -> Bool
`equalWireHost` T_px -> Domain
pxMapX400 T_px
b

instance Ord T_px where
    T_px
a compare :: T_px -> T_px -> Ordering
`compare` T_px
b = T_px -> Word16
pxPref    T_px
a Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         T_px -> Word16
pxPref    T_px
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_px -> Domain
pxMap822  T_px
a Domain -> Domain -> Ordering
`compareWireHost` T_px -> Domain
pxMap822  T_px
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_px -> Domain
pxMapX400 T_px
a Domain -> Domain -> Ordering
`compareWireHost` T_px -> Domain
pxMapX400 T_px
b

instance Presentable T_px where
    present :: T_px -> Builder -> Builder
present T_PX{Word16
Domain
pxPref :: T_px -> Word16
pxMap822 :: T_px -> Domain
pxMapX400 :: T_px -> Domain
pxPref :: Word16
pxMap822 :: Domain
pxMapX400 :: Domain
..} =
        Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
pxPref
        (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
pxMap822
        (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
pxMapX400

instance KnownRData T_px where
    rdType :: forall b -> (b ~ T_px) => RRTYPE
rdType _ = RRTYPE
PX
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_px -> SPut s RData
rdEncode T_PX{Word16
Domain
pxPref :: T_px -> Word16
pxMap822 :: T_px -> Domain
pxMapX400 :: T_px -> Domain
pxPref :: Word16
pxMap822 :: Domain
pxMapX400 :: 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
pxPref
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
pxMap822
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
pxMapX400
    cnEncode :: forall s. T_px -> SPut s RData
cnEncode T_PX{Word16
Domain
pxPref :: T_px -> Word16
pxMap822 :: T_px -> Domain
pxMapX400 :: T_px -> Domain
pxPref :: Word16
pxMap822 :: Domain
pxMapX400 :: Domain
..} =
        T_px -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_px -> SPut s RData
rdEncode (T_px -> SPut s RData) -> T_px -> SPut s RData
forall a b. (a -> b) -> a -> b
$ Word16 -> Domain -> Domain -> T_px
T_PX Word16
pxPref
                        (Domain -> Domain
canonicalise Domain
pxMap822)
                        (Domain -> Domain
canonicalise Domain
pxMapX400)
    rdDecode :: forall b ->
(b ~ T_px) => RDataExtensionVal T_px -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_px
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        pxPref    <- SGet Word16
get16
        pxMap822  <- getDomain
        pxMapX400 <- getDomain
        pure $ RData T_PX{..}

-- | The @GPOS@ resource record
-- ([RFC 1712 section 3](https://www.rfc-editor.org/rfc/rfc1712.html#section-3))
-- — an early geographical-location record: longitude, latitude,
-- and altitude as three DNS /character-strings/ holding decimal
-- floating-point text.  Superseded by @LOC@-style records and not
-- used in modern zone data.
--
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                 LONGITUDE                  /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                  LATITUDE                  /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                  ALTITUDE                  /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
--
-- The 'Ord' instance compares the three fields as DNS
-- character-strings, agreeing with the canonical wire-form
-- ordering of
-- [RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2).
data T_gpos = T_GPOS
    { T_gpos -> ShortByteString
gposLongitude :: SB.ShortByteString
    , T_gpos -> ShortByteString
gposLatitude  :: SB.ShortByteString
    , T_gpos -> ShortByteString
gposAltitude  :: SB.ShortByteString
    } deriving (T_gpos -> T_gpos -> Bool
(T_gpos -> T_gpos -> Bool)
-> (T_gpos -> T_gpos -> Bool) -> Eq T_gpos
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_gpos -> T_gpos -> Bool
== :: T_gpos -> T_gpos -> Bool
$c/= :: T_gpos -> T_gpos -> Bool
/= :: T_gpos -> T_gpos -> Bool
Eq, Int -> T_gpos -> ShowS
[T_gpos] -> ShowS
T_gpos -> String
(Int -> T_gpos -> ShowS)
-> (T_gpos -> String) -> ([T_gpos] -> ShowS) -> Show T_gpos
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_gpos -> ShowS
showsPrec :: Int -> T_gpos -> ShowS
$cshow :: T_gpos -> String
show :: T_gpos -> String
$cshowList :: [T_gpos] -> ShowS
showList :: [T_gpos] -> ShowS
Show)

instance Ord T_gpos where
    T_gpos
a compare :: T_gpos -> T_gpos -> Ordering
`compare` T_gpos
b = T_gpos -> ShortByteString
gposLongitude T_gpos
a ShortByteString -> ShortByteString -> Ordering
`strCompare` T_gpos -> ShortByteString
gposLongitude T_gpos
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_gpos -> ShortByteString
gposLatitude  T_gpos
a ShortByteString -> ShortByteString -> Ordering
`strCompare` T_gpos -> ShortByteString
gposLatitude  T_gpos
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_gpos -> ShortByteString
gposAltitude  T_gpos
a ShortByteString -> ShortByteString -> Ordering
`strCompare` T_gpos -> ShortByteString
gposAltitude  T_gpos
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_gpos where
    present :: T_gpos -> Builder -> Builder
present T_GPOS{ShortByteString
gposLongitude :: T_gpos -> ShortByteString
gposLatitude :: T_gpos -> ShortByteString
gposAltitude :: T_gpos -> ShortByteString
gposLongitude :: ShortByteString
gposLatitude :: ShortByteString
gposAltitude :: ShortByteString
..} =
        forall a. Presentable a => a -> Builder -> Builder
present     @DnsText (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
gposLongitude)
        (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
gposLatitude)
        (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
gposAltitude)

instance KnownRData T_gpos where
    rdType :: forall b -> (b ~ T_gpos) => RRTYPE
rdType _ = RRTYPE
GPOS
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_gpos -> SPut s RData
rdEncode T_GPOS{ShortByteString
gposLongitude :: T_gpos -> ShortByteString
gposLatitude :: T_gpos -> ShortByteString
gposAltitude :: T_gpos -> ShortByteString
gposLongitude :: ShortByteString
gposLatitude :: ShortByteString
gposAltitude :: ShortByteString
..} = 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
$
        ShortByteString -> SizedBuilder
mbShortByteStringLen8    ShortByteString
gposLongitude
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
gposLatitude
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
gposAltitude
    rdDecode :: forall b ->
(b ~ T_gpos) => RDataExtensionVal T_gpos -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_gpos
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        gposLongitude <- SGet ShortByteString
getShortByteStringLen8
        gposLatitude  <- getShortByteStringLen8
        gposAltitude  <- getShortByteStringLen8
        pure $ RData T_GPOS{..}

-- | The @KX@ resource record
-- ([RFC 2230 section 3.1](https://www.rfc-editor.org/rfc/rfc2230.html#section-3.1))
-- — names a Key Exchange host for the owner: a 16-bit preference
-- and a 'Domain' naming the exchanger.  Defined for the DNSSEC
-- precursor work; never widely deployed.
--
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > |                  PREFERENCE                   |
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-- > /                   EXCHANGER                   /
-- > /                                               /
-- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
--
-- The exchanger field is not subject to wire-form name compression
-- ([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 exchanger in canonical
-- wire form (via 'equalWireHost' / 'compareWireHost'), so 'Ord'
-- is canonical.
data T_kx = T_KX
    { T_kx -> Word16
kxPref :: Word16
    , T_kx -> Domain
kxExch :: Domain
    } deriving (Int -> T_kx -> ShowS
[T_kx] -> ShowS
T_kx -> String
(Int -> T_kx -> ShowS)
-> (T_kx -> String) -> ([T_kx] -> ShowS) -> Show T_kx
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_kx -> ShowS
showsPrec :: Int -> T_kx -> ShowS
$cshow :: T_kx -> String
show :: T_kx -> String
$cshowList :: [T_kx] -> ShowS
showList :: [T_kx] -> ShowS
Show)

instance Eq T_kx where
    T_kx
a == :: T_kx -> T_kx -> Bool
== T_kx
b = T_kx -> Word16
kxPref T_kx
a Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
==              T_kx -> Word16
kxPref T_kx
b
          Bool -> Bool -> Bool
&& T_kx -> Domain
kxExch T_kx
a Domain -> Domain -> Bool
`equalWireHost` T_kx -> Domain
kxExch T_kx
b

instance Ord T_kx where
    T_kx
a compare :: T_kx -> T_kx -> Ordering
`compare` T_kx
b = T_kx -> Word16
kxPref T_kx
a Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         T_kx -> Word16
kxPref T_kx
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_kx -> Domain
kxExch T_kx
a Domain -> Domain -> Ordering
`compareWireHost` T_kx -> Domain
kxExch T_kx
b

instance Presentable T_kx where
    present :: T_kx -> Builder -> Builder
present T_KX{Word16
Domain
kxPref :: T_kx -> Word16
kxExch :: T_kx -> Domain
kxPref :: Word16
kxExch :: Domain
..} = Word16 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word16
kxPref (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
kxExch

instance KnownRData T_kx where
    rdType :: forall b -> (b ~ T_kx) => RRTYPE
rdType _ = RRTYPE
KX
    {-# INLINE rdType #-}

    rdEncode :: forall s. T_kx -> SPut s RData
rdEncode T_KX{Word16
Domain
kxPref :: T_kx -> Word16
kxExch :: T_kx -> Domain
kxPref :: Word16
kxExch :: 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
kxPref
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Domain -> SizedBuilder
mbWireForm Domain
kxExch
    cnEncode :: forall s. T_kx -> SPut s RData
cnEncode rd :: T_kx
rd@(T_KX{kxExch :: T_kx -> Domain
kxExch = Domain
d}) =
        T_kx -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_kx -> SPut s RData
rdEncode T_kx
rd {kxExch = canonicalise d}
    rdDecode :: forall b ->
(b ~ T_kx) => RDataExtensionVal T_kx -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_kx
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        kxPref <- SGet Word16
get16
        kxExch <- getDomainNC
        pure $ RData T_KX{..}

-- | The @A6@ resource record
-- ([RFC 2874 section 3.1](https://www.rfc-editor.org/rfc/rfc2874.html#section-3.1);
-- obsoleted by [RFC 6563](https://www.rfc-editor.org/rfc/rfc6563.html))
-- — an experimental chained IPv6 addressing scheme.  Each record
-- carries a prefix length, an address suffix containing the
-- low-order bits, and a 'Domain' naming where to look up the
-- remaining prefix bits.  Resolution walked the chain to assemble
-- the full address.  The deployment experience reported in RFC
-- 6563 led to A6 being abandoned in favour of plain 'Net.DNSBase.RData.A.T_aaaa'
-- records.
--
-- > +-----------+------------------+-------------------+
-- > |Prefix len.|  Address suffix  |    Prefix name    |
-- > | (1 octet) |  (0..16 octets)  |  (0..255 octets)  |
-- > +-----------+------------------+-------------------+
--
-- The wire encoding rules are:
--
-- * The prefix length is an unsigned octet between 0 and 128.
-- * The address-suffix field carries exactly enough octets to
--   hold @128 - /prefix-length/@ bits, with up to seven leading
--   pad bits set to zero so the field is an integral number of
--   bytes.
-- * The prefix-name field is a wire-form 'Domain'.  It is absent
--   when the prefix length is zero (the suffix already holds the
--   whole address); the suffix field is absent when the prefix
--   length is 128 (the whole address comes from the chain).
-- * The prefix-name is not subject to wire-form name compression
--   ([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 prefix-name field in
-- canonical wire form (via 'toHost'), so 'Ord' is canonical.
data T_a6 = T_a6
    { T_a6 -> Word8
a6Prefix :: Word8
    , T_a6 -> IPv6
a6Suffix :: IPv6
    , T_a6 -> Maybe Domain
a6Domain :: Maybe Domain
    } deriving (Int -> T_a6 -> ShowS
[T_a6] -> ShowS
T_a6 -> String
(Int -> T_a6 -> ShowS)
-> (T_a6 -> String) -> ([T_a6] -> ShowS) -> Show T_a6
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_a6 -> ShowS
showsPrec :: Int -> T_a6 -> ShowS
$cshow :: T_a6 -> String
show :: T_a6 -> String
$cshowList :: [T_a6] -> ShowS
showList :: [T_a6] -> ShowS
Show)

instance Eq T_a6 where
    T_a6
a == :: T_a6 -> T_a6 -> Bool
== T_a6
b = (           T_a6 -> Word8
a6Prefix T_a6
a) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== (           T_a6 -> Word8
a6Prefix T_a6
b)
          Bool -> Bool -> Bool
&& (           T_a6 -> IPv6
a6Suffix T_a6
a) IPv6 -> IPv6 -> Bool
forall a. Eq a => a -> a -> Bool
== (           T_a6 -> IPv6
a6Suffix T_a6
b)
          Bool -> Bool -> Bool
&& (Domain -> Host
toHost (Domain -> Host) -> Maybe Domain -> Maybe Host
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> T_a6 -> Maybe Domain
a6Domain T_a6
a) Maybe Host -> Maybe Host -> Bool
forall a. Eq a => a -> a -> Bool
== (Domain -> Host
toHost (Domain -> Host) -> Maybe Domain -> Maybe Host
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> T_a6 -> Maybe Domain
a6Domain T_a6
b)

instance Ord T_a6 where
    T_a6
a compare :: T_a6 -> T_a6 -> Ordering
`compare` T_a6
b = (           T_a6 -> Word8
a6Prefix T_a6
a) Word8 -> Word8 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (           T_a6 -> Word8
a6Prefix T_a6
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (           T_a6 -> IPv6
a6Suffix T_a6
a) IPv6 -> IPv6 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (           T_a6 -> IPv6
a6Suffix T_a6
b)
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (Domain -> Host
toHost (Domain -> Host) -> Maybe Domain -> Maybe Host
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> T_a6 -> Maybe Domain
a6Domain T_a6
a) Maybe Host -> Maybe Host -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (Domain -> Host
toHost (Domain -> Host) -> Maybe Domain -> Maybe Host
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> T_a6 -> Maybe Domain
a6Domain T_a6
b)

-- | /Smart constructor/ for @A6@ records:
--
-- - Silently caps the prefix length to 128
-- - Ignores the domain when the prefix length is 0
-- - Otherwise, uses the root domain if no domain is provided
--
pattern T_A6 :: Word8 -> IPv6 -> Maybe Domain -> T_a6
pattern $mT_A6 :: forall {r}.
T_a6 -> (Word8 -> IPv6 -> Maybe Domain -> r) -> ((# #) -> r) -> r
$bT_A6 :: Word8 -> IPv6 -> Maybe Domain -> T_a6
T_A6 prefix suffix domain <- T_a6 prefix suffix domain where
    T_A6 Word8
prefix IPv6
suffix Maybe Domain
domain = T_a6{Maybe Domain
Word8
IPv6
a6Prefix :: Word8
a6Suffix :: IPv6
a6Domain :: Maybe Domain
a6Prefix :: Word8
a6Domain :: Maybe Domain
a6Suffix :: IPv6
..}
      where
        a6Prefix :: Word8
a6Prefix = Word8 -> Word8 -> Bool -> Word8
forall a. a -> a -> Bool -> a
bool Word8
128 Word8
prefix (Word8
prefix Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
128)
        a6Domain :: Maybe Domain
a6Domain | Word8
prefix Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0 = Maybe Domain
forall a. Maybe a
Nothing
                 | Bool
otherwise   = Domain -> Maybe Domain
forall a. a -> Maybe a
Just (Domain -> Maybe Domain) -> Domain -> Maybe Domain
forall a b. (a -> b) -> a -> b
$! Domain -> Maybe Domain -> Domain
forall a. a -> Maybe a -> a
fromMaybe Domain
RootDomain Maybe Domain
domain
        a6Suffix :: IPv6
a6Suffix | (Word32
s0, Word32
s1, Word32
s2, Word32
s3) <- IPv6 -> (Word32, Word32, Word32, Word32)
fromIPv6w IPv6
suffix
                   = (Word32, Word32, Word32, Word32) -> IPv6
toIPv6w (Word32
s0 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
m0, Word32
s1 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
m1, Word32
s2 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
m2, Word32
s3 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
m3)
          where
            (Word32
m0, Word32
m1, Word32
m2, Word32
m3) = Int -> (Word32, Word32, Word32, Word32)
mask128 (Int -> (Word32, Word32, Word32, Word32))
-> Int -> (Word32, Word32, Word32, Word32)
forall a b. (a -> b) -> a -> b
$ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a6Prefix

instance Presentable T_a6 where
    present :: T_a6 -> Builder -> Builder
present T_a6{Maybe Domain
Word8
IPv6
a6Prefix :: T_a6 -> Word8
a6Suffix :: T_a6 -> IPv6
a6Domain :: T_a6 -> Maybe Domain
a6Prefix :: Word8
a6Suffix :: IPv6
a6Domain :: Maybe Domain
..} =
        Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Word8
a6Prefix
        (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
a6Suffix
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> Builder)
-> (Domain -> Builder -> Builder)
-> Maybe Domain
-> Builder
-> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Builder -> Builder
forall a. a -> a
id Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Maybe Domain
a6Domain

instance KnownRData T_a6 where
    rdType :: forall b -> (b ~ T_a6) => RRTYPE
rdType _ = RRTYPE
A6
    {-# INLINE rdType #-}

    rdEncode :: forall s. T_a6 -> SPut s RData
rdEncode T_a6{Maybe Domain
Word8
IPv6
a6Prefix :: T_a6 -> Word8
a6Suffix :: T_a6 -> IPv6
a6Domain :: T_a6 -> Maybe Domain
a6Prefix :: Word8
a6Suffix :: IPv6
a6Domain :: Maybe 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
$
        Word8 -> SizedBuilder
mbWord8 Word8
a6Prefix
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> [SizedBuilder] -> SizedBuilder
forall a. Monoid a => [a] -> a
mconcat [Word8 -> SizedBuilder
mbWord8 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
w) | Int
w <- [Int]
bytesFromIPv6]
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> SizedBuilder
-> (Domain -> SizedBuilder) -> Maybe Domain -> SizedBuilder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe SizedBuilder
forall a. Monoid a => a
mempty Domain -> SizedBuilder
mbWireForm Maybe Domain
a6Domain
      where
        npad :: Int
npad = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a6Prefix Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
3
        bytesFromIPv6 :: [Int]
bytesFromIPv6 = Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
drop Int
npad ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ IPv6 -> [Int]
fromIPv6b IPv6
a6Suffix

    cnEncode :: forall s. T_a6 -> SPut s RData
cnEncode rd :: T_a6
rd@(T_a6{a6Domain :: T_a6 -> Maybe Domain
a6Domain = Just Domain
d}) =
        T_a6 -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_a6 -> SPut s RData
rdEncode T_a6
rd {a6Domain = Just (canonicalise d)}
    cnEncode T_a6
rd = T_a6 -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_a6 -> SPut s RData
rdEncode T_a6
rd

    rdDecode :: forall b ->
(b ~ T_a6) => RDataExtensionVal T_a6 -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_a6
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        a6Prefix <- SGet Word8
get8
        when (a6Prefix > 128) do
            failSGet "A6 prefix exceeds 128"
        let npad = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a6Prefix Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
3
        a6Suffix <- bytesToIPv6 npad <$> getNBytes (16 - npad)
        a6Domain <- if | a6Prefix == 0 -> pure Nothing
                       | otherwise     -> Just <$> getDomainNC
        pure $ RData T_a6{..}
      where
        bytesToIPv6 :: Int -> [a] -> IPv6
bytesToIPv6 Int
npad = [Int] -> IPv6
toIPv6b ([Int] -> IPv6) -> ([a] -> [Int]) -> [a] -> IPv6
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
npad Int
0 [Int] -> [Int] -> [Int]
forall a. [a] -> [a] -> [a]
++) ([Int] -> [Int]) -> ([a] -> [Int]) -> [a] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Int) -> [a] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral

--------------------

-- | Mask upper @p@ bits of IPv6 address.
mask128 :: Int -> (Word32, Word32, Word32, Word32)
mask128 :: Int -> (Word32, Word32, Word32, Word32)
mask128 Int
p | Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
64    = (Word32
w0, Word32
w1, Word32
m32, Word32
m32)
          | Bool
otherwise = (Word32
0,   Word32
0,  Word32
w2,  Word32
w3)
  where
    m64 :: Word64
m64 = Word64
0xffff_ffff_ffff_ffff :: Word64
    m32 :: Word32
m32 = Word32
0xffff_ffff :: Word32
    hi :: Word64
hi = Word64
m64 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
p
    lo :: Word64
lo = Word64
m64 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` (Int
p Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
64)
    w0 :: Word32
w0 = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word64 @Word32 (Word64
hi Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
32)
    w1 :: Word32
w1 = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word64 @Word32 Word64
hi
    w2 :: Word32
w2 = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word64 @Word32 (Word64
lo Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
32)
    w3 :: Word32
w3 = forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word64 @Word32 Word64
lo