-- |
-- Module      : Net.DNSBase.Internal.RCODE
-- Description : TBD
-- Copyright   : (c) Viktor Dukhovni, 2026
-- License     : BSD-3-Clause
-- Maintainer  : ietf-dane@dukhovni.org
-- Stability   : unstable
module Net.DNSBase.Internal.RCODE
    ( RCODE
        ( RCODE
        , NOERROR
        , FORMERR
        , SERVFAIL
        , NXDOMAIN
        , NOTIMP
        , REFUSED
        , YXDOMAIN
        , YXRRSET
        , NXRRSET
        , NOTAUTH
        , NOTZONE
        , DSOTYPENI
        , BADVERS
        , BADSIG
        , BADKEY
        , BADTIME
        , BADMODE
        , BADNAME
        , BADALG
        , BADTRUNC
        , BADCOOKIE
        )
    , extendRCODE
    ) where

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

-- | The extended (12-bit) DNS RCODE consisting of 4 bits from the basic DNS
-- header, possibly augmented with 8 more bits from the EDNS header.
--
-- Should always be zero in well-formed requests.  When decoding replies, the
-- high eight bits from any EDNS response are combined with the 4-bit RCODE
-- from the DNS header.  When encoding a message, if EDNS is disabled RCODE
-- values larger than 15 are mapped to 'FORMERR'.
--
-- RCODES 12 through 15 are reserved, see
-- [IANA](https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6)
newtype RCODE = RC_ Word16 deriving (RCODE -> RCODE -> Bool
(RCODE -> RCODE -> Bool) -> (RCODE -> RCODE -> Bool) -> Eq RCODE
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RCODE -> RCODE -> Bool
== :: RCODE -> RCODE -> Bool
$c/= :: RCODE -> RCODE -> Bool
/= :: RCODE -> RCODE -> Bool
Eq, Eq RCODE
Eq RCODE =>
(RCODE -> RCODE -> Ordering)
-> (RCODE -> RCODE -> Bool)
-> (RCODE -> RCODE -> Bool)
-> (RCODE -> RCODE -> Bool)
-> (RCODE -> RCODE -> Bool)
-> (RCODE -> RCODE -> RCODE)
-> (RCODE -> RCODE -> RCODE)
-> Ord RCODE
RCODE -> RCODE -> Bool
RCODE -> RCODE -> Ordering
RCODE -> RCODE -> RCODE
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 :: RCODE -> RCODE -> Ordering
compare :: RCODE -> RCODE -> Ordering
$c< :: RCODE -> RCODE -> Bool
< :: RCODE -> RCODE -> Bool
$c<= :: RCODE -> RCODE -> Bool
<= :: RCODE -> RCODE -> Bool
$c> :: RCODE -> RCODE -> Bool
> :: RCODE -> RCODE -> Bool
$c>= :: RCODE -> RCODE -> Bool
>= :: RCODE -> RCODE -> Bool
$cmax :: RCODE -> RCODE -> RCODE
max :: RCODE -> RCODE -> RCODE
$cmin :: RCODE -> RCODE -> RCODE
min :: RCODE -> RCODE -> RCODE
Ord, Int -> RCODE
RCODE -> Int
RCODE -> [RCODE]
RCODE -> RCODE
RCODE -> RCODE -> [RCODE]
RCODE -> RCODE -> RCODE -> [RCODE]
(RCODE -> RCODE)
-> (RCODE -> RCODE)
-> (Int -> RCODE)
-> (RCODE -> Int)
-> (RCODE -> [RCODE])
-> (RCODE -> RCODE -> [RCODE])
-> (RCODE -> RCODE -> [RCODE])
-> (RCODE -> RCODE -> RCODE -> [RCODE])
-> Enum RCODE
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: RCODE -> RCODE
succ :: RCODE -> RCODE
$cpred :: RCODE -> RCODE
pred :: RCODE -> RCODE
$ctoEnum :: Int -> RCODE
toEnum :: Int -> RCODE
$cfromEnum :: RCODE -> Int
fromEnum :: RCODE -> Int
$cenumFrom :: RCODE -> [RCODE]
enumFrom :: RCODE -> [RCODE]
$cenumFromThen :: RCODE -> RCODE -> [RCODE]
enumFromThen :: RCODE -> RCODE -> [RCODE]
$cenumFromTo :: RCODE -> RCODE -> [RCODE]
enumFromTo :: RCODE -> RCODE -> [RCODE]
$cenumFromThenTo :: RCODE -> RCODE -> RCODE -> [RCODE]
enumFromThenTo :: RCODE -> RCODE -> RCODE -> [RCODE]
Enum, Int -> RCODE -> ShowS
[RCODE] -> ShowS
RCODE -> String
(Int -> RCODE -> ShowS)
-> (RCODE -> String) -> ([RCODE] -> ShowS) -> Show RCODE
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RCODE -> ShowS
showsPrec :: Int -> RCODE -> ShowS
$cshow :: RCODE -> String
show :: RCODE -> String
$cshowList :: [RCODE] -> ShowS
showList :: [RCODE] -> ShowS
Show)

instance Bounded RCODE where
    minBound :: RCODE
minBound = Word16 -> RCODE
RC_ Word16
0
    maxBound :: RCODE
maxBound = Word16 -> RCODE
RC_ Word16
0xfff

-- | Smart constructor ensures provided values are valid.
-- Attempts to construct a values larger than 4095 raises an error.
pattern RCODE :: Word16 -> RCODE
pattern $mRCODE :: forall {r}. RCODE -> (Word16 -> r) -> ((# #) -> r) -> r
$bRCODE :: Word16 -> RCODE
RCODE w <- RC_ w where
    RCODE Word16
w
        | Word16 -> RCODE
RC_ Word16
w RCODE -> RCODE -> Bool
forall a. Ord a => a -> a -> Bool
<= RCODE
forall a. Bounded a => a
maxBound = Word16 -> RCODE
RC_ Word16
w
        | Bool
otherwise         = String -> RCODE
forall a. HasCallStack => String -> a
error String
"RCODE out of range"
{-# COMPLETE RCODE #-}

-- | Combine basic header RCODE (low 4 bits)
-- with EDNS extended RCODE (high 8 bits)
extendRCODE :: RCODE -> Word8 -> RCODE
extendRCODE :: RCODE -> Word8 -> RCODE
extendRCODE (RCODE Word16
lo) Word8
hi =
    Word16 -> RCODE
RCODE (Word16 -> RCODE) -> Word16 -> RCODE
forall a b. (a -> b) -> a -> b
$ (Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
hi Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`shiftL` Int
4) Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. (Word16
lo Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.&. Word16
0xF)


instance Presentable RCODE where
    present :: RCODE -> Builder -> Builder
present RCODE
NOERROR    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NOERROR"
    present RCODE
FORMERR    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"FORMERR"
    present RCODE
SERVFAIL   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"SERVFAIL"
    present RCODE
NXDOMAIN   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NXDOMAIN"
    present RCODE
NOTIMP     = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NOTIMP"
    present RCODE
REFUSED    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"REFUSED"
    present RCODE
YXDOMAIN   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"YXDOMAIN"
    present RCODE
YXRRSET    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"YXRRSET"
    present RCODE
NXRRSET    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NXRRSET"
    present RCODE
NOTAUTH    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NOTAUTH"
    present RCODE
NOTZONE    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NOTZONE"
    present RCODE
DSOTYPENI  = forall a. Presentable a => a -> Builder -> Builder
present @String String
"DSOTYPENI"
    present RCODE
BADVERS    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADVERS"
    present RCODE
BADSIG     = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADSIG"
    present RCODE
BADKEY     = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADKEY"
    present RCODE
BADTIME    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADTIME"
    present RCODE
BADMODE    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADMODE"
    present RCODE
BADNAME    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADNAME"
    present RCODE
BADALG     = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADALG"
    present RCODE
BADTRUNC   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADTRUNC"
    present RCODE
BADCOOKIE  = forall a. Presentable a => a -> Builder -> Builder
present @String String
"BADCOOKIE"
    present (RC_ Word16
rc)   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"RCODE" (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
present Word16
rc

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

-- | NOERROR - [RFC1035]
pattern NOERROR :: RCODE
pattern $mNOERROR :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bNOERROR :: RCODE
NOERROR = RCODE 0

-- | FORMERR - [RFC1035]
pattern FORMERR :: RCODE
pattern $mFORMERR :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bFORMERR :: RCODE
FORMERR = RCODE 1

-- | SERVFAIL - [RFC1035]
pattern SERVFAIL :: RCODE
pattern $mSERVFAIL :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bSERVFAIL :: RCODE
SERVFAIL = RCODE 2

-- | NXDOMAIN - [RFC1035]
pattern NXDOMAIN     :: RCODE
pattern $mNXDOMAIN :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bNXDOMAIN :: RCODE
NXDOMAIN     = RCODE 3

-- | NOTIMP - [RFC1035]
pattern NOTIMP       :: RCODE
pattern $mNOTIMP :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bNOTIMP :: RCODE
NOTIMP       = RCODE 4

-- | REFUSED - [RFC1035]
pattern REFUSED      :: RCODE
pattern $mREFUSED :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bREFUSED :: RCODE
REFUSED      = RCODE 5

-- | YXDOMAIN - [RFC2136][RFC6672]
pattern YXDOMAIN     :: RCODE
pattern $mYXDOMAIN :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bYXDOMAIN :: RCODE
YXDOMAIN     = RCODE 6

-- | YXRRSET - [RFC2136]
pattern YXRRSET      :: RCODE
pattern $mYXRRSET :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bYXRRSET :: RCODE
YXRRSET      = RCODE 7

-- | NXRRSET - [RFC2136]
pattern NXRRSET      :: RCODE
pattern $mNXRRSET :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bNXRRSET :: RCODE
NXRRSET      = RCODE 8

-- | NOTAUTH - [RFC2136]
pattern NOTAUTH      :: RCODE
pattern $mNOTAUTH :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bNOTAUTH :: RCODE
NOTAUTH      = RCODE 9

-- | NOTZONE - [RFC2136]
pattern NOTZONE      :: RCODE
pattern $mNOTZONE :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bNOTZONE :: RCODE
NOTZONE      = RCODE 10

-- | DSOTYPENI - [RFC8490]
pattern DSOTYPENI    :: RCODE
pattern $mDSOTYPENI :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bDSOTYPENI :: RCODE
DSOTYPENI    = RCODE 11

-- | BADVERS - [RFC6891]
pattern BADVERS      :: RCODE
pattern $mBADVERS :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADVERS :: RCODE
BADVERS      = RCODE 16

-- | BADSIG - [RFC2845]
pattern BADSIG       :: RCODE
pattern $mBADSIG :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADSIG :: RCODE
BADSIG       = RCODE 16

-- | BADKEY - [RFC2845]
pattern BADKEY       :: RCODE
pattern $mBADKEY :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADKEY :: RCODE
BADKEY       = RCODE 17

-- | BADTIME - [RFC2845]
pattern BADTIME      :: RCODE
pattern $mBADTIME :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADTIME :: RCODE
BADTIME      = RCODE 18

-- | BADMODE - [RFC2930]
pattern BADMODE      :: RCODE
pattern $mBADMODE :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADMODE :: RCODE
BADMODE      = RCODE 19

-- | BADNAME - [RFC2930]
pattern BADNAME      :: RCODE
pattern $mBADNAME :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADNAME :: RCODE
BADNAME      = RCODE 20

-- | BADALG - [RFC2930]
pattern BADALG       :: RCODE
pattern $mBADALG :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADALG :: RCODE
BADALG       = RCODE 21

-- | BADTRUNC - [RFC4635]
pattern BADTRUNC     :: RCODE
pattern $mBADTRUNC :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADTRUNC :: RCODE
BADTRUNC     = RCODE 22

-- | BADCOOKIE - [RFC7873]
pattern BADCOOKIE    :: RCODE
pattern $mBADCOOKIE :: forall {r}. RCODE -> ((# #) -> r) -> ((# #) -> r) -> r
$bBADCOOKIE :: RCODE
BADCOOKIE    = RCODE 23