{-|
Module      : Net.DNSBase.RData.NSEC
Description : DNSSEC denial-of-existence records (NSEC, NSEC3, NSEC3PARAM, NXT)
Copyright   : (c) Viktor Dukhovni, 2026
License     : BSD-3-Clause
Maintainer  : ietf-dane@dukhovni.org
Stability   : unstable

DNSSEC denial-of-existence machinery.  'T_nsec' (RFC 4034) names
the next existing owner in canonical order alongside a bitmap of
present RR types at the proving name.  'T_nsec3' (RFC 5155) is
the hashed variant, where the next-name pointer is the hashed
owner.  'T_nsec3param' (RFC 5155) carries the zone-wide NSEC3
hashing parameters at the zone apex.  'T_nxt' (RFC 2535) is the
obsolete predecessor of NSEC, defined here for compatibility
with archival zone data.
-}
{-# LANGUAGE
    NegativeLiterals
  , RecordWildCards
  #-}
module Net.DNSBase.RData.NSEC
    ( -- * NSEC, NSEC3, and NSEC Type Bitmap structures
      T_nsec(..)
    , T_nsec3(..)
    , T_nsec3param(..)
    , NsecTypes
    , nsecTypesFromList
    , nsecTypesToList
    , hasRRtype
    -- * Obsolete NXT structure
    , T_nxt(..)
    , NxtTypes
    , NxtRRtype
    , toNxtTypes
    , nxtTypesFromNE
    , nxtTypesToNE
    , hasNxtRRtype
    , module Net.DNSBase.NonEmpty
    ) where

import qualified Data.ByteString.Short as SB

import Net.DNSBase.Internal.Util

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.NonEmpty
import Net.DNSBase.NsecTypes
import Net.DNSBase.Present
import Net.DNSBase.RData
import Net.DNSBase.RRTYPE
import Net.DNSBase.Secalgs
import Net.DNSBase.Text

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

-- | The @NSEC@ resource record
-- ([RFC 4034 section 4](https://datatracker.ietf.org/doc/html/rfc4034#section-4))
-- — the building block of authenticated denial of existence: a
-- 'Domain' naming the next existing owner in the zone's canonical
-- order, plus an 'NsecTypes' bitmap of RR types present at the
-- proving name.
--
-- The next-owner-name field is not subject to wire-form name
-- compression
-- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4))
-- and is not lower-cased when computing canonical wire form
-- ([RFC 6840 section 5.1](https://datatracker.ietf.org/doc/html/rfc6840#section-5.1)).
--
-- See 'T_nsec3' for the hashed-name variant.
data T_nsec = T_NSEC
    { T_nsec -> Domain
nsecNext  :: Domain
    , T_nsec -> NsecTypes
nsecTypes :: NsecTypes
    } deriving (T_nsec -> T_nsec -> Bool
(T_nsec -> T_nsec -> Bool)
-> (T_nsec -> T_nsec -> Bool) -> Eq T_nsec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_nsec -> T_nsec -> Bool
== :: T_nsec -> T_nsec -> Bool
$c/= :: T_nsec -> T_nsec -> Bool
/= :: T_nsec -> T_nsec -> Bool
Eq, Int -> T_nsec -> ShowS
[T_nsec] -> ShowS
T_nsec -> String
(Int -> T_nsec -> ShowS)
-> (T_nsec -> String) -> ([T_nsec] -> ShowS) -> Show T_nsec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_nsec -> ShowS
showsPrec :: Int -> T_nsec -> ShowS
$cshow :: T_nsec -> String
show :: T_nsec -> String
$cshowList :: [T_nsec] -> ShowS
showList :: [T_nsec] -> ShowS
Show)

instance Ord T_nsec where
    T_nsec
a compare :: T_nsec -> T_nsec -> Ordering
`compare` T_nsec
b = T_nsec -> Domain
nsecNext  T_nsec
a Domain -> Domain -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` T_nsec -> Domain
nsecNext  T_nsec
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nsec -> NsecTypes
nsecTypes T_nsec
a NsecTypes -> NsecTypes -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` T_nsec -> NsecTypes
nsecTypes T_nsec
b

instance Presentable T_nsec where
    present :: T_nsec -> Builder -> Builder
present T_NSEC{Domain
NsecTypes
nsecNext :: T_nsec -> Domain
nsecTypes :: T_nsec -> NsecTypes
nsecNext :: Domain
nsecTypes :: NsecTypes
..} =
        Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present     Domain
nsecNext
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NsecTypes -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp NsecTypes
nsecTypes

instance KnownRData T_nsec where
    rdType :: forall b -> (b ~ T_nsec) => RRTYPE
rdType _ = RRTYPE
NSEC
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_nsec -> SPut s RData
rdEncode T_NSEC{Domain
NsecTypes
nsecNext :: T_nsec -> Domain
nsecTypes :: T_nsec -> NsecTypes
nsecNext :: Domain
nsecTypes :: NsecTypes
..} = do
        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
nsecNext
        NsecTypes -> SPut s RData
forall s. NsecTypes -> SPut s RData
putNsecTypes NsecTypes
nsecTypes
    rdDecode :: forall b ->
(b ~ T_nsec) => RDataExtensionVal T_nsec -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_nsec
_ Int
len = do
        pos0 <- SGet Int
getPosition
        nsecNext  <- getDomainNC
        used <- subtract pos0 <$> getPosition
        nsecTypes <- getNsecTypes (len - used)
        pure $ RData T_NSEC{..}

-- | The @NSEC3@ resource record
-- ([RFC 5155 section 3.2](https://tools.ietf.org/html/rfc5155#section-3.2))
-- — the hashed denial-of-existence variant.  The next-owner-name
-- field carries the hashed equivalent rather than the plain name,
-- and the record itself includes the hashing parameters
-- (algorithm, flags, iteration count, salt) needed to reproduce
-- the hash.  The trailing 'NsecTypes' bitmap names the RR types
-- present at the proving (un-hashed) name.
--
-- >                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |   Hash Alg.   |     Flags     |          Iterations           |
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |  Salt Length  |                     Salt                      /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |  Hash Length  |             Next Hashed Owner Name            /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > /                         Type Bit Maps                         /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
-- The 'Ord' instance compares the fields in wire-encoding order,
-- using 'dnsTextCmp' on the length-prefixed salt and hashed-name
-- bytes, so it agrees with the canonical RR-content ordering of
-- [RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2).
--
-- See 'T_nsec' for the un-hashed variant and 'T_nsec3param' for the
-- zone-apex parameter record.
data T_nsec3 = T_NSEC3
    { T_nsec3 -> NSEC3HashAlg
nsec3Alg   :: NSEC3HashAlg
    , T_nsec3 -> Word8
nsec3Flags :: Word8
    , T_nsec3 -> Word16
nsec3Iters :: Word16
    , T_nsec3 -> ShortByteString
nsec3Salt  :: ShortByteString
    , T_nsec3 -> ShortByteString
nsec3Next  :: ShortByteString
    , T_nsec3 -> NsecTypes
nsec3Types :: NsecTypes
    } deriving (T_nsec3 -> T_nsec3 -> Bool
(T_nsec3 -> T_nsec3 -> Bool)
-> (T_nsec3 -> T_nsec3 -> Bool) -> Eq T_nsec3
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_nsec3 -> T_nsec3 -> Bool
== :: T_nsec3 -> T_nsec3 -> Bool
$c/= :: T_nsec3 -> T_nsec3 -> Bool
/= :: T_nsec3 -> T_nsec3 -> Bool
Eq)

instance Ord T_nsec3 where
    T_nsec3
a compare :: T_nsec3 -> T_nsec3 -> Ordering
`compare` T_nsec3
b = T_nsec3 -> NSEC3HashAlg
nsec3Alg   T_nsec3
a NSEC3HashAlg -> NSEC3HashAlg -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`    T_nsec3 -> NSEC3HashAlg
nsec3Alg   T_nsec3
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nsec3 -> Word8
nsec3Flags T_nsec3
a Word8 -> Word8 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`    T_nsec3 -> Word8
nsec3Flags T_nsec3
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nsec3 -> Word16
nsec3Iters T_nsec3
a Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`    T_nsec3 -> Word16
nsec3Iters T_nsec3
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nsec3 -> ShortByteString
nsec3Salt  T_nsec3
a ShortByteString -> ShortByteString -> Ordering
forall a. Coercible a ShortByteString => a -> a -> Ordering
`dnsTextCmp` T_nsec3 -> ShortByteString
nsec3Salt  T_nsec3
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nsec3 -> ShortByteString
nsec3Next  T_nsec3
a ShortByteString -> ShortByteString -> Ordering
forall a. Coercible a ShortByteString => a -> a -> Ordering
`dnsTextCmp` T_nsec3 -> ShortByteString
nsec3Next  T_nsec3
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nsec3 -> NsecTypes
nsec3Types T_nsec3
a NsecTypes -> NsecTypes -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`    T_nsec3 -> NsecTypes
nsec3Types T_nsec3
b

instance Show T_nsec3 where
    showsPrec :: Int -> T_nsec3 -> ShowS
showsPrec Int
p T_NSEC3{Word8
Word16
ShortByteString
NSEC3HashAlg
NsecTypes
nsec3Alg :: T_nsec3 -> NSEC3HashAlg
nsec3Flags :: T_nsec3 -> Word8
nsec3Iters :: T_nsec3 -> Word16
nsec3Salt :: T_nsec3 -> ShortByteString
nsec3Next :: T_nsec3 -> ShortByteString
nsec3Types :: T_nsec3 -> NsecTypes
nsec3Alg :: NSEC3HashAlg
nsec3Flags :: Word8
nsec3Iters :: Word16
nsec3Salt :: ShortByteString
nsec3Next :: ShortByteString
nsec3Types :: NsecTypes
..} = Int -> ShowS -> ShowS
showsP Int
p (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString String
"T_NSEC3 "
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NSEC3HashAlg -> ShowS
forall a. Show a => a -> ShowS
shows'   NSEC3HashAlg
nsec3Alg   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
. Word8 -> ShowS
forall a. Show a => a -> ShowS
shows'   Word8
nsec3Flags 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
nsec3Iters 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
. ShortByteString -> ShowS
showSalt ShortByteString
nsec3Salt  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
. ShortByteString -> ShowS
forall {a}. Coercible a ByteArray => a -> ShowS
showNext ShortByteString
nsec3Next  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
. NsecTypes -> ShowS
forall a. Show a => a -> ShowS
shows'   NsecTypes
nsec3Types
      where
        showNext :: a -> ShowS
showNext a
s = forall a. Show a => a -> ShowS
shows @Bytes32 (a -> Bytes32
forall a b. Coercible a b => a -> b
coerce a
s)
        showSalt :: ShortByteString -> ShowS
showSalt ShortByteString
s | ShortByteString -> Bool
SB.null ShortByteString
s = Char -> ShowS
showChar Char
'-'
                   | Bool
otherwise = forall a. Show a => a -> ShowS
shows @Bytes16 (ShortByteString -> Bytes16
forall a b. Coercible a b => a -> b
coerce ShortByteString
s)

instance Presentable T_nsec3 where
    present :: T_nsec3 -> Builder -> Builder
present T_NSEC3{Word8
Word16
ShortByteString
NSEC3HashAlg
NsecTypes
nsec3Alg :: T_nsec3 -> NSEC3HashAlg
nsec3Flags :: T_nsec3 -> Word8
nsec3Iters :: T_nsec3 -> Word16
nsec3Salt :: T_nsec3 -> ShortByteString
nsec3Next :: T_nsec3 -> ShortByteString
nsec3Types :: T_nsec3 -> NsecTypes
nsec3Alg :: NSEC3HashAlg
nsec3Flags :: Word8
nsec3Iters :: Word16
nsec3Salt :: ShortByteString
nsec3Next :: ShortByteString
nsec3Types :: NsecTypes
..} =
        NSEC3HashAlg -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present       NSEC3HashAlg
nsec3Alg
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp   Word8
nsec3Flags
        (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
nsec3Iters
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> Builder -> Builder
presentSalt ShortByteString
nsec3Salt
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> Builder -> Builder
forall {a}. Coercible a ByteArray => a -> Builder -> Builder
presentNext ShortByteString
nsec3Next
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NsecTypes -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp   NsecTypes
nsec3Types
      where
        presentNext :: a -> Builder -> Builder
presentNext a
s = forall a. Presentable a => a -> Builder -> Builder
presentSp @Bytes32 (a -> Bytes32
forall a b. Coercible a b => a -> b
coerce a
s)
        presentSalt :: ShortByteString -> Builder -> Builder
presentSalt ShortByteString
s | ShortByteString -> Bool
SB.null ShortByteString
s = Char -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Char
'-'
                      | Bool
otherwise = forall a. Presentable a => a -> Builder -> Builder
presentSp @Bytes16 (ShortByteString -> Bytes16
forall a b. Coercible a b => a -> b
coerce ShortByteString
s)

instance KnownRData T_nsec3 where
    rdType :: forall b -> (b ~ T_nsec3) => RRTYPE
rdType _ = RRTYPE
NSEC3
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_nsec3 -> SPut s RData
rdEncode T_NSEC3{Word8
Word16
ShortByteString
NSEC3HashAlg
NsecTypes
nsec3Alg :: T_nsec3 -> NSEC3HashAlg
nsec3Flags :: T_nsec3 -> Word8
nsec3Iters :: T_nsec3 -> Word16
nsec3Salt :: T_nsec3 -> ShortByteString
nsec3Next :: T_nsec3 -> ShortByteString
nsec3Types :: T_nsec3 -> NsecTypes
nsec3Alg :: NSEC3HashAlg
nsec3Flags :: Word8
nsec3Iters :: Word16
nsec3Salt :: ShortByteString
nsec3Next :: ShortByteString
nsec3Types :: NsecTypes
..} = do
        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) -> NSEC3HashAlg -> SizedBuilder
forall a b. Coercible a b => a -> b
coerce Word8 -> SizedBuilder
mbWord8 NSEC3HashAlg
nsec3Alg
            SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word8 -> SizedBuilder
mbWord8 Word8
nsec3Flags
            SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word16 -> SizedBuilder
mbWord16 Word16
nsec3Iters
            SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
nsec3Salt
            SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
nsec3Next
        NsecTypes -> SPut s RData
forall s. NsecTypes -> SPut s RData
putNsecTypes NsecTypes
nsec3Types
    rdDecode :: forall b ->
(b ~ T_nsec3) => RDataExtensionVal T_nsec3 -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_nsec3
_ Int
len = do
        pos0 <- SGet Int
getPosition
        nsec3Alg   <- NSEC3HashAlg <$> get8
        nsec3Flags <- get8
        nsec3Iters <- get16
        nsec3Salt  <- getShortByteStringLen8
        nsec3Next  <- getShortByteStringLen8
        used       <- subtract pos0 <$> getPosition
        nsec3Types <- getNsecTypes (len - used)
        pure $ RData T_NSEC3{..}

-- | The @NSEC3PARAM@ resource record
-- ([RFC 5155 section 4.2](https://tools.ietf.org/html/rfc5155#section-4.2))
-- — a zone-apex record describing the NSEC3 hashing parameters
-- (algorithm, iteration count, salt) in use across the zone's
-- NSEC3 chain.  Validating resolvers do not consult this record
-- (each 'T_nsec3' carries its own parameters in the RDATA); it
-- exists for authoritative-server tooling.
--
-- >                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |   Hash Alg.   |     Flags     |          Iterations           |
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |  Salt Length  |                     Salt                      /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
-- (Editorial: the salt and iteration count were largely a bad
-- idea in retrospect; best practice for zone signers is to set
-- the salt empty and the iteration count to zero.)
--
-- See 'T_nsec3' for the records produced under these parameters.
data T_nsec3param = T_NSEC3PARAM
    { T_nsec3param -> NSEC3HashAlg
nsec3paramAlg   :: NSEC3HashAlg
    , T_nsec3param -> Word8
nsec3paramFlags :: Word8
    , T_nsec3param -> Word16
nsec3paramIters :: Word16
    , T_nsec3param -> ShortByteString
nsec3paramSalt  :: ShortByteString
    } deriving (T_nsec3param -> T_nsec3param -> Bool
(T_nsec3param -> T_nsec3param -> Bool)
-> (T_nsec3param -> T_nsec3param -> Bool) -> Eq T_nsec3param
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: T_nsec3param -> T_nsec3param -> Bool
== :: T_nsec3param -> T_nsec3param -> Bool
$c/= :: T_nsec3param -> T_nsec3param -> Bool
/= :: T_nsec3param -> T_nsec3param -> Bool
Eq, Int -> T_nsec3param -> ShowS
[T_nsec3param] -> ShowS
T_nsec3param -> String
(Int -> T_nsec3param -> ShowS)
-> (T_nsec3param -> String)
-> ([T_nsec3param] -> ShowS)
-> Show T_nsec3param
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> T_nsec3param -> ShowS
showsPrec :: Int -> T_nsec3param -> ShowS
$cshow :: T_nsec3param -> String
show :: T_nsec3param -> String
$cshowList :: [T_nsec3param] -> ShowS
showList :: [T_nsec3param] -> ShowS
Show)

instance Ord T_nsec3param where
    compare :: T_nsec3param -> T_nsec3param -> Ordering
compare T_nsec3param
a T_nsec3param
b =
       (T_nsec3param -> NSEC3HashAlg)
-> T_nsec3param -> T_nsec3param -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing T_nsec3param -> NSEC3HashAlg
nsec3paramAlg T_nsec3param
a T_nsec3param
b
       Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_nsec3param -> Word8) -> T_nsec3param -> T_nsec3param -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing T_nsec3param -> Word8
nsec3paramFlags T_nsec3param
a T_nsec3param
b
       Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (T_nsec3param -> Word16)
-> T_nsec3param -> T_nsec3param -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing T_nsec3param -> Word16
nsec3paramIters T_nsec3param
a T_nsec3param
b
       Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> ShortByteString -> Ordering
forall a. Coercible a ShortByteString => a -> a -> Ordering
dnsTextCmp (T_nsec3param -> ShortByteString
nsec3paramSalt  T_nsec3param
a) (T_nsec3param -> ShortByteString
nsec3paramSalt  T_nsec3param
b)

instance Presentable T_nsec3param where
    present :: T_nsec3param -> Builder -> Builder
present T_NSEC3PARAM{Word8
Word16
ShortByteString
NSEC3HashAlg
nsec3paramAlg :: T_nsec3param -> NSEC3HashAlg
nsec3paramFlags :: T_nsec3param -> Word8
nsec3paramIters :: T_nsec3param -> Word16
nsec3paramSalt :: T_nsec3param -> ShortByteString
nsec3paramAlg :: NSEC3HashAlg
nsec3paramFlags :: Word8
nsec3paramIters :: Word16
nsec3paramSalt :: ShortByteString
..} =
        NSEC3HashAlg -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present       NSEC3HashAlg
nsec3paramAlg
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp   Word8
nsec3paramFlags
        (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
nsec3paramIters
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> Builder -> Builder
presentSalt ShortByteString
nsec3paramSalt
      where
        presentSalt :: ShortByteString -> Builder -> Builder
presentSalt ShortByteString
s | ShortByteString -> Bool
SB.null ShortByteString
s = Char -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp Char
'-'
                      | Bool
otherwise = forall a. Presentable a => a -> Builder -> Builder
presentSp @Bytes16 (ShortByteString -> Bytes16
forall a b. Coercible a b => a -> b
coerce ShortByteString
s)

instance KnownRData T_nsec3param where
    rdType :: forall b -> (b ~ T_nsec3param) => RRTYPE
rdType _ = RRTYPE
NSEC3PARAM
    {-# INLINE rdType #-}
    rdEncode :: forall s. T_nsec3param -> SPut s RData
rdEncode T_NSEC3PARAM{Word8
Word16
ShortByteString
NSEC3HashAlg
nsec3paramAlg :: T_nsec3param -> NSEC3HashAlg
nsec3paramFlags :: T_nsec3param -> Word8
nsec3paramIters :: T_nsec3param -> Word16
nsec3paramSalt :: T_nsec3param -> ShortByteString
nsec3paramAlg :: NSEC3HashAlg
nsec3paramFlags :: Word8
nsec3paramIters :: Word16
nsec3paramSalt :: 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
$
        Word8 -> SizedBuilder
mbWord8 (NSEC3HashAlg -> Word8
forall a b. Coercible a b => a -> b
coerce NSEC3HashAlg
nsec3paramAlg)
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word8 -> SizedBuilder
mbWord8 Word8
nsec3paramFlags
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> Word16 -> SizedBuilder
mbWord16 Word16
nsec3paramIters
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteStringLen8 ShortByteString
nsec3paramSalt
    rdDecode :: forall b ->
(b ~ T_nsec3param) =>
RDataExtensionVal T_nsec3param -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_nsec3param
_ = SGet RData -> Int -> SGet RData
forall a b. a -> b -> a
const do
        nsec3paramAlg   <- Word8 -> NSEC3HashAlg
NSEC3HashAlg (Word8 -> NSEC3HashAlg) -> SGet Word8 -> SGet NSEC3HashAlg
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet Word8
get8
        nsec3paramFlags <- get8
        nsec3paramIters <- get16
        nsec3paramSalt  <- getShortByteStringLen8
        pure $ RData T_NSEC3PARAM{..}

-- | The @NXT@ resource record
-- ([RFC 2535 section 5.2](https://www.rfc-editor.org/rfc/rfc2535.html#section-5.2))
-- — the obsolete predecessor of 'T_nsec', defined here for
-- compatibility with archival DNSSEC zone data.  Same conceptual
-- shape as @NSEC@ (next owner name + type bitmap) but with a
-- different type-bitmap encoding.
--
-- >                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |                  next domain name                             /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-- > |                    type bit map                               /
-- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
--
-- The domain name is wire-form name-compressed on decode only
-- ([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 domain field in
-- canonical wire form (via 'equalWireHost' / 'compareWireHost')
-- and the type bitmap byte-wise.
--
-- See 'T_nsec' for the modern replacement.
data T_nxt = T_NXT
    { T_nxt -> Domain
nxtNext :: Domain
    , T_nxt -> NxtTypes
nxtBits :: NxtTypes
    }

instance Show T_nxt where
    showsPrec :: Int -> T_nxt -> ShowS
showsPrec Int
p T_NXT{Domain
NxtTypes
nxtNext :: T_nxt -> Domain
nxtBits :: T_nxt -> NxtTypes
nxtNext :: Domain
nxtBits :: NxtTypes
..} = Int -> ShowS -> ShowS
showsP Int
p (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString String
"T_NXT "
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Domain -> ShowS
forall a. Show a => a -> ShowS
shows' Domain
nxtNext 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
. NxtTypes -> ShowS
forall a. Show a => a -> ShowS
shows' NxtTypes
nxtBits

instance Eq T_nxt where
    T_nxt
a == :: T_nxt -> T_nxt -> Bool
== T_nxt
b = T_nxt -> Domain
nxtNext  T_nxt
a Domain -> Domain -> Bool
`equalWireHost` T_nxt -> Domain
nxtNext  T_nxt
b
          Bool -> Bool -> Bool
&& T_nxt -> NxtTypes
nxtBits  T_nxt
a NxtTypes -> NxtTypes -> Bool
forall a. Eq a => a -> a -> Bool
==              T_nxt -> NxtTypes
nxtBits  T_nxt
b

instance Ord T_nxt where
    T_nxt
a compare :: T_nxt -> T_nxt -> Ordering
`compare` T_nxt
b = T_nxt -> Domain
nxtNext T_nxt
a Domain -> Domain -> Ordering
`compareWireHost` T_nxt -> Domain
nxtNext T_nxt
b
                 Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> T_nxt -> NxtTypes
nxtBits T_nxt
a NxtTypes -> NxtTypes -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare`         T_nxt -> NxtTypes
nxtBits T_nxt
b

instance Presentable T_nxt where
    present :: T_nxt -> Builder -> Builder
present T_NXT{Domain
NxtTypes
nxtNext :: T_nxt -> Domain
nxtBits :: T_nxt -> NxtTypes
nxtNext :: Domain
nxtBits :: NxtTypes
..} =
        Domain -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Domain
nxtNext
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NxtTypes -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
presentSp NxtTypes
nxtBits

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

    rdEncode :: forall s. T_nxt -> SPut s RData
rdEncode T_NXT{Domain
NxtTypes
nxtNext :: T_nxt -> Domain
nxtBits :: T_nxt -> NxtTypes
nxtNext :: Domain
nxtBits :: NxtTypes
..} = 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
nxtNext
        SizedBuilder -> SizedBuilder -> SizedBuilder
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> SizedBuilder
mbShortByteString (NxtTypes -> ShortByteString
forall a b. Coercible a b => a -> b
coerce NxtTypes
nxtBits)

    cnEncode :: forall s. T_nxt -> SPut s RData
cnEncode rd :: T_nxt
rd@(T_NXT{nxtNext :: T_nxt -> Domain
nxtNext = Domain
d}) =
        T_nxt -> SPut s RData
forall a s. KnownRData a => a -> SPut s RData
forall s. T_nxt -> SPut s RData
rdEncode T_nxt
rd {nxtNext = canonicalise d}

    rdDecode :: forall b ->
(b ~ T_nxt) => RDataExtensionVal T_nxt -> Int -> SGet RData
rdDecode _ RDataExtensionVal T_nxt
_ Int
len = do
        pos0    <- SGet Int
getPosition
        nxtNext <- getDomain
        used    <- subtract pos0 <$> getPosition
        nxtBits <- getNxtTypes (len - used)
        pure $ RData $ T_NXT{..}