-- |
-- Module      : Net.DNSBase.Internal.Opcode
-- Description : TBD
-- Copyright   : (c) Viktor Dukhovni, 2026
-- License     : BSD-3-Clause
-- Maintainer  : ietf-dane@dukhovni.org
-- Stability   : unstable
module Net.DNSBase.Internal.Opcode
    ( Opcode
        ( Opcode
        , Query
        , IQuery
        , Status
        , Notify
        , Update
        , DSO
        )
    ) where

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

-- | The DNS request Opcode from the basic DNS header.  Attempts to construct
-- an 'Opcode' larger than 15 will produce in an error.
--
newtype Opcode = Op_ Word8 deriving (Opcode -> Opcode -> Bool
(Opcode -> Opcode -> Bool)
-> (Opcode -> Opcode -> Bool) -> Eq Opcode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Opcode -> Opcode -> Bool
== :: Opcode -> Opcode -> Bool
$c/= :: Opcode -> Opcode -> Bool
/= :: Opcode -> Opcode -> Bool
Eq, Eq Opcode
Eq Opcode =>
(Opcode -> Opcode -> Ordering)
-> (Opcode -> Opcode -> Bool)
-> (Opcode -> Opcode -> Bool)
-> (Opcode -> Opcode -> Bool)
-> (Opcode -> Opcode -> Bool)
-> (Opcode -> Opcode -> Opcode)
-> (Opcode -> Opcode -> Opcode)
-> Ord Opcode
Opcode -> Opcode -> Bool
Opcode -> Opcode -> Ordering
Opcode -> Opcode -> Opcode
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 :: Opcode -> Opcode -> Ordering
compare :: Opcode -> Opcode -> Ordering
$c< :: Opcode -> Opcode -> Bool
< :: Opcode -> Opcode -> Bool
$c<= :: Opcode -> Opcode -> Bool
<= :: Opcode -> Opcode -> Bool
$c> :: Opcode -> Opcode -> Bool
> :: Opcode -> Opcode -> Bool
$c>= :: Opcode -> Opcode -> Bool
>= :: Opcode -> Opcode -> Bool
$cmax :: Opcode -> Opcode -> Opcode
max :: Opcode -> Opcode -> Opcode
$cmin :: Opcode -> Opcode -> Opcode
min :: Opcode -> Opcode -> Opcode
Ord, Int -> Opcode
Opcode -> Int
Opcode -> [Opcode]
Opcode -> Opcode
Opcode -> Opcode -> [Opcode]
Opcode -> Opcode -> Opcode -> [Opcode]
(Opcode -> Opcode)
-> (Opcode -> Opcode)
-> (Int -> Opcode)
-> (Opcode -> Int)
-> (Opcode -> [Opcode])
-> (Opcode -> Opcode -> [Opcode])
-> (Opcode -> Opcode -> [Opcode])
-> (Opcode -> Opcode -> Opcode -> [Opcode])
-> Enum Opcode
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 :: Opcode -> Opcode
succ :: Opcode -> Opcode
$cpred :: Opcode -> Opcode
pred :: Opcode -> Opcode
$ctoEnum :: Int -> Opcode
toEnum :: Int -> Opcode
$cfromEnum :: Opcode -> Int
fromEnum :: Opcode -> Int
$cenumFrom :: Opcode -> [Opcode]
enumFrom :: Opcode -> [Opcode]
$cenumFromThen :: Opcode -> Opcode -> [Opcode]
enumFromThen :: Opcode -> Opcode -> [Opcode]
$cenumFromTo :: Opcode -> Opcode -> [Opcode]
enumFromTo :: Opcode -> Opcode -> [Opcode]
$cenumFromThenTo :: Opcode -> Opcode -> Opcode -> [Opcode]
enumFromThenTo :: Opcode -> Opcode -> Opcode -> [Opcode]
Enum, Int -> Opcode -> ShowS
[Opcode] -> ShowS
Opcode -> String
(Int -> Opcode -> ShowS)
-> (Opcode -> String) -> ([Opcode] -> ShowS) -> Show Opcode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Opcode -> ShowS
showsPrec :: Int -> Opcode -> ShowS
$cshow :: Opcode -> String
show :: Opcode -> String
$cshowList :: [Opcode] -> ShowS
showList :: [Opcode] -> ShowS
Show)

instance Bounded Opcode where
    minBound :: Opcode
minBound = Word8 -> Opcode
Op_ Word8
0
    maxBound :: Opcode
maxBound = Word8 -> Opcode
Op_ Word8
0xf

{-# COMPLETE Opcode #-}
pattern Opcode :: Word8 -> Opcode
pattern $mOpcode :: forall {r}. Opcode -> (Word8 -> r) -> ((# #) -> r) -> r
$bOpcode :: Word8 -> Opcode
Opcode w <- Op_ w where
    Opcode Word8
w
        | Word8 -> Opcode
Op_ Word8
w Opcode -> Opcode -> Bool
forall a. Ord a => a -> a -> Bool
<= Opcode
forall a. Bounded a => a
maxBound = Word8 -> Opcode
Op_ Word8
w
        | Bool
otherwise         = String -> Opcode
forall a. HasCallStack => String -> a
error String
"Opcode out of range"

-- | The 'Presentable' instance outputs BIND-compatible names.
instance Presentable Opcode where
    present :: Opcode -> Builder -> Builder
present Opcode
Query    = forall a. Presentable a => a -> Builder -> Builder
present @String String
"QUERY"
    present Opcode
IQuery   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"IQUERY"
    present Opcode
Status   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"STATUS"
    present Opcode
Notify   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"NOTIFY"
    present Opcode
Update   = forall a. Presentable a => a -> Builder -> Builder
present @String String
"UPDATE"
    present Opcode
DSO      = forall a. Presentable a => a -> Builder -> Builder
present @String String
"DSO"
    present (Op_ Word8
op) = forall a. Presentable a => a -> Builder -> Builder
present @String String
"OPCODE" (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
present Word8
op

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

-- | Query - [RFC1035]
pattern Query        :: Opcode
pattern $mQuery :: forall {r}. Opcode -> ((# #) -> r) -> ((# #) -> r) -> r
$bQuery :: Opcode
Query         = Opcode 0

-- | IQuery - [RFC3425]
pattern IQuery       :: Opcode
pattern $mIQuery :: forall {r}. Opcode -> ((# #) -> r) -> ((# #) -> r) -> r
$bIQuery :: Opcode
IQuery        = Opcode 1

-- | Status - [RFC1035]
pattern Status       :: Opcode
pattern $mStatus :: forall {r}. Opcode -> ((# #) -> r) -> ((# #) -> r) -> r
$bStatus :: Opcode
Status        = Opcode 2

-- | Notify - [RFC1996]
pattern Notify       :: Opcode
pattern $mNotify :: forall {r}. Opcode -> ((# #) -> r) -> ((# #) -> r) -> r
$bNotify :: Opcode
Notify        = Opcode 4

-- | Update - [RFC2136]
pattern Update       :: Opcode
pattern $mUpdate :: forall {r}. Opcode -> ((# #) -> r) -> ((# #) -> r) -> r
$bUpdate :: Opcode
Update        = Opcode 5

-- | DSO - [RFC8490] DNS Stateful Operations
pattern DSO          :: Opcode
pattern $mDSO :: forall {r}. Opcode -> ((# #) -> r) -> ((# #) -> r) -> r
$bDSO :: Opcode
DSO           = Opcode 6