{-|
Module      : Net.DNSBase.RData.SVCB.SPV
Description : Concrete value types for SVCB / HTTPS service parameters
Copyright   : (c) Viktor Dukhovni, 2026
License     : BSD-3-Clause
Maintainer  : ietf-dane@dukhovni.org
Stability   : unstable

One 'KnownSVCParamValue' instance per standardised service
parameter key.  Each type corresponds to a 'SVCParamKey' from
the IANA registry and carries the value payload for that key
in a form suited to the application that consumes it (a port
as 'Word16', address hints as a 'NonEmpty' of 'IPv4' / 'IPv6',
and so on).

An unknown key falls through to
'Net.DNSBase.RData.SVCB.OpaqueSPV', which preserves the raw wire
bytes.  Applications register additional typed values at runtime
via 'Net.DNSBase.Resolver.extendRRwithType' on the @SVCB@ or
@HTTPS@ RR type — see "Net.DNSBase.Extensible" for a worked
example.
-}

module Net.DNSBase.RData.SVCB.SPV
    ( SPV_mandatory(SPV_MANDATORY)
    , SPV_alpn(..)
    , SPV_ndalpn(..)
    , SPV_port(..)
    , SPV_ipv4hint(..)
    , SPV_ipv6hint(..)
    , SPV_ech(..)
    , SPV_dohpath(..)
    , SPV_docpath(..)
    , SPV_tlsgroups(..)
    , SPV_pvd(..)
    ) where

import qualified Data.ByteString.Short as SB
import qualified Data.List.NonEmpty as NE
import qualified Data.Set as Set
import qualified Data.Text as T
import qualified Data.Text.Unsafe as T
import Data.Set (Set)

import Net.DNSBase.Internal.Util

import Net.DNSBase.Bytes
import Net.DNSBase.Decode.State
import Net.DNSBase.Encode.Metric
import Net.DNSBase.Encode.State
import Net.DNSBase.NonEmpty
import Net.DNSBase.Present
import Net.DNSBase.RData.SVCB.SPVList
import Net.DNSBase.RData.SVCB.SVCParamKey
import Net.DNSBase.RData.SVCB.SVCParamValue
import Net.DNSBase.Text

-- | The @mandatory@ service parameter
-- ([RFC 9460 section 8](https://datatracker.ietf.org/doc/html/rfc9460#section-8))
-- — the set of additional 'SVCParamKey' codes a client must
-- recognise to make sense of this RR, on top of any keys that
-- are automatically mandatory for the application protocol.  A
-- client that does not understand all the listed keys must
-- ignore the RR.
--
-- The set may not be empty on the wire (an empty list is
-- encoded as the parameter being absent) and may hold at most
-- 32767 keys.  The constructor is not exported; build instances
-- via 'fromNonEmptyList' or by combining values with their
-- 'Semigroup' instance.
newtype SPV_mandatory = SPV_mandatory (Set SVCParamKey)
    deriving (SPV_mandatory -> SPV_mandatory -> Bool
(SPV_mandatory -> SPV_mandatory -> Bool)
-> (SPV_mandatory -> SPV_mandatory -> Bool) -> Eq SPV_mandatory
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_mandatory -> SPV_mandatory -> Bool
== :: SPV_mandatory -> SPV_mandatory -> Bool
$c/= :: SPV_mandatory -> SPV_mandatory -> Bool
/= :: SPV_mandatory -> SPV_mandatory -> Bool
Eq, NonEmpty SPV_mandatory -> SPV_mandatory
SPV_mandatory -> SPV_mandatory -> SPV_mandatory
(SPV_mandatory -> SPV_mandatory -> SPV_mandatory)
-> (NonEmpty SPV_mandatory -> SPV_mandatory)
-> (forall b. Integral b => b -> SPV_mandatory -> SPV_mandatory)
-> Semigroup SPV_mandatory
forall b. Integral b => b -> SPV_mandatory -> SPV_mandatory
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: SPV_mandatory -> SPV_mandatory -> SPV_mandatory
<> :: SPV_mandatory -> SPV_mandatory -> SPV_mandatory
$csconcat :: NonEmpty SPV_mandatory -> SPV_mandatory
sconcat :: NonEmpty SPV_mandatory -> SPV_mandatory
$cstimes :: forall b. Integral b => b -> SPV_mandatory -> SPV_mandatory
stimes :: forall b. Integral b => b -> SPV_mandatory -> SPV_mandatory
Semigroup)

-- | One-way pattern exposing the underlying key set for lookups.
-- Construction is available only via 'fromNonEmptyList' or via the
-- 'Semigroup' instance.
pattern SPV_MANDATORY :: Set SVCParamKey -- ^ The keys as a 'Set'
                      -> SPV_mandatory
pattern $mSPV_MANDATORY :: forall {r}.
SPV_mandatory -> (Set SVCParamKey -> r) -> ((# #) -> r) -> r
SPV_MANDATORY s <- SPV_mandatory s
{-# COMPLETE SPV_MANDATORY #-}

instance Show SPV_mandatory where
    showsPrec :: Int -> SPV_mandatory -> ShowS
showsPrec Int
p (SPV_mandatory Set SVCParamKey
s) = Int -> ShowS -> ShowS
showsP Int
p (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString String
"fromNonEmptyList @SPV_mandatory "
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty SVCParamKey -> ShowS
forall a. Show a => a -> ShowS
shows' ([SVCParamKey] -> NonEmpty SVCParamKey
forall a. HasCallStack => [a] -> NonEmpty a
NE.fromList ([SVCParamKey] -> NonEmpty SVCParamKey)
-> [SVCParamKey] -> NonEmpty SVCParamKey
forall a b. (a -> b) -> a -> b
$ Set SVCParamKey -> [SVCParamKey]
forall a. Set a -> [a]
Set.toList Set SVCParamKey
s)

instance IsNonEmptyList SPV_mandatory where
    type Item1 SPV_mandatory = SVCParamKey
    fromNonEmptyList :: NonEmpty (Item1 SPV_mandatory) -> SPV_mandatory
fromNonEmptyList = Set SVCParamKey -> SPV_mandatory
forall a b. Coercible a b => a -> b
coerce (Set SVCParamKey -> SPV_mandatory)
-> (NonEmpty SVCParamKey -> Set SVCParamKey)
-> NonEmpty SVCParamKey
-> SPV_mandatory
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [SVCParamKey] -> Set SVCParamKey
forall a. Ord a => [a] -> Set a
Set.fromList ([SVCParamKey] -> Set SVCParamKey)
-> (NonEmpty SVCParamKey -> [SVCParamKey])
-> NonEmpty SVCParamKey
-> Set SVCParamKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty SVCParamKey -> [SVCParamKey]
forall a. NonEmpty a -> [a]
NE.toList
    toNonEmptyList :: SPV_mandatory -> NonEmpty (Item1 SPV_mandatory)
toNonEmptyList = [SVCParamKey] -> NonEmpty SVCParamKey
forall a. HasCallStack => [a] -> NonEmpty a
NE.fromList ([SVCParamKey] -> NonEmpty SVCParamKey)
-> (SPV_mandatory -> [SVCParamKey])
-> SPV_mandatory
-> NonEmpty SVCParamKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set SVCParamKey -> [SVCParamKey]
forall a. Set a -> [a]
Set.toList (Set SVCParamKey -> [SVCParamKey])
-> (SPV_mandatory -> Set SVCParamKey)
-> SPV_mandatory
-> [SVCParamKey]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SPV_mandatory -> Set SVCParamKey
forall a b. Coercible a b => a -> b
coerce

-- | Wire-form order
instance Ord SPV_mandatory where
    SPV_MANDATORY Set SVCParamKey
a compare :: SPV_mandatory -> SPV_mandatory -> Ordering
`compare` SPV_MANDATORY Set SVCParamKey
b =
        (Set SVCParamKey -> Int)
-> Set SVCParamKey -> Set SVCParamKey -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Set SVCParamKey -> Int
forall a. Set a -> Int
Set.size Set SVCParamKey
a Set SVCParamKey
b
        Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (Set SVCParamKey -> [SVCParamKey])
-> Set SVCParamKey -> Set SVCParamKey -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Set SVCParamKey -> [SVCParamKey]
forall a. Set a -> [a]
Set.toList Set SVCParamKey
a Set SVCParamKey
b

instance Presentable SPV_mandatory where
    present :: SPV_mandatory -> Builder -> Builder
present (SPV_MANDATORY ([SVCParamKey] -> NonEmpty SVCParamKey
forall a. HasCallStack => [a] -> NonEmpty a
NE.fromList ([SVCParamKey] -> NonEmpty SVCParamKey)
-> (Set SVCParamKey -> [SVCParamKey])
-> Set SVCParamKey
-> NonEmpty SVCParamKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set SVCParamKey -> [SVCParamKey]
forall a. Set a -> [a]
Set.toList -> SVCParamKey
key :| [SVCParamKey]
keys)) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
MANDATORY
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SVCParamKey -> Builder -> Builder
pfst SVCParamKey
key
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> [SVCParamKey] -> Builder)
-> [SVCParamKey] -> Builder -> Builder
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((SVCParamKey -> Builder -> Builder)
-> Builder -> [SVCParamKey] -> Builder
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr SVCParamKey -> Builder -> Builder
pnxt) [SVCParamKey]
keys
      where
        pfst :: SVCParamKey -> Builder -> Builder
pfst = Char -> SVCParamKey -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
'='
        pnxt :: SVCParamKey -> Builder -> Builder
pnxt = Char -> SVCParamKey -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
','

instance KnownSVCParamValue SPV_mandatory where
    spvKey :: forall b -> (b ~ SPV_mandatory) => SVCParamKey
spvKey _ = SVCParamKey
MANDATORY
    encodeSPV :: forall r s. ErrorContext r => SPV_mandatory -> SPut s r
encodeSPV (SPV_MANDATORY (Set SVCParamKey -> Set SVCParamKey
forall a b. Coercible a b => a -> b
coerce -> Set SVCParamKey
ks)) = do
        Bool -> SPutM s r () -> SPutM s r ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Set SVCParamKey -> Int
forall a. Set a -> Int
Set.size Set SVCParamKey
ks Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0x7fff) do (forall a. ErrorContext a => a -> EncodeErr a) -> SPutM s r ()
forall r s.
ErrorContext r =>
(forall a. ErrorContext a => a -> EncodeErr a) -> SPut s r
failWith a -> EncodeErr a
forall r. (Typeable r, Show r, Eq r) => r -> EncodeErr r
forall a. ErrorContext a => a -> EncodeErr a
CantEncode
        SizedBuilder -> SPutM s r ()
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPutM s r ()) -> SizedBuilder -> SPutM s r ()
forall a b. (a -> b) -> a -> b
$ (Word16 -> SizedBuilder) -> [Word16] -> SizedBuilder
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Word16 -> SizedBuilder
mbWord16
                        ([Word16] -> SizedBuilder) -> [Word16] -> SizedBuilder
forall a b. (a -> b) -> a -> b
$ forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @[SVCParamKey] @[Word16] ([SVCParamKey] -> [Word16]) -> [SVCParamKey] -> [Word16]
forall a b. (a -> b) -> a -> b
$ Set SVCParamKey -> [SVCParamKey]
forall a. Set a -> [a]
Set.toList Set SVCParamKey
ks

    -- | Decode the mandatory key list.
    -- XXX: Does not yet enforce ascending order, non-duplication,
    -- self-exclusion, or exclusion of automatically mandatory keys, all of
    -- which are required by the SVCB draft:
    -- <https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-12#section-2.2>,
    -- <https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-12#section-8>
    --
    -- The resulting keyset will however be de-duplicated and ordered.
    --
    decodeSPV :: forall b -> (b ~ SPV_mandatory) => Int -> SGet SVCParamValue
decodeSPV _ Int
len = do
        k <- Word16 -> SVCParamKey
mkKey (Word16 -> SVCParamKey) -> SGet Word16 -> SGet SVCParamKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet Word16
get16
        ks <- getFixedWidthSequence 2 (mkKey <$> get16) (len - 2)
        pure $ SVCParamValue $ mkMandatory $ Set.fromList $ k : ks
      where
        mkKey :: Word16 -> SVCParamKey
        mkKey :: Word16 -> SVCParamKey
mkKey = Word16 -> SVCParamKey
forall a b. Coercible a b => a -> b
coerce
        mkMandatory :: Set SVCParamKey -> SPV_mandatory
        mkMandatory :: Set SVCParamKey -> SPV_mandatory
mkMandatory = Set SVCParamKey -> SPV_mandatory
forall a b. Coercible a b => a -> b
coerce

-- | The @alpn@ service parameter
-- ([RFC 9460 section 7.1](https://datatracker.ietf.org/doc/html/rfc9460#section-7.1))
-- — the set of Application-Layer Protocol Negotiation
-- ([RFC 7301](https://datatracker.ietf.org/doc/html/rfc7301))
-- protocol identifiers this service endpoint supports.  Together
-- with 'SPV_ndalpn' it defines the SVCB ALPN set: by default the
-- scheme's protocol is implicitly included, and 'SPV_ndalpn'
-- suppresses that default.
newtype SPV_alpn = SPV_ALPN (NonEmpty ShortByteString)
    deriving (SPV_alpn -> SPV_alpn -> Bool
(SPV_alpn -> SPV_alpn -> Bool)
-> (SPV_alpn -> SPV_alpn -> Bool) -> Eq SPV_alpn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_alpn -> SPV_alpn -> Bool
== :: SPV_alpn -> SPV_alpn -> Bool
$c/= :: SPV_alpn -> SPV_alpn -> Bool
/= :: SPV_alpn -> SPV_alpn -> Bool
Eq, Int -> SPV_alpn -> ShowS
[SPV_alpn] -> ShowS
SPV_alpn -> String
(Int -> SPV_alpn -> ShowS)
-> (SPV_alpn -> String) -> ([SPV_alpn] -> ShowS) -> Show SPV_alpn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_alpn -> ShowS
showsPrec :: Int -> SPV_alpn -> ShowS
$cshow :: SPV_alpn -> String
show :: SPV_alpn -> String
$cshowList :: [SPV_alpn] -> ShowS
showList :: [SPV_alpn] -> ShowS
Show)

instance Ord SPV_alpn where
    (SPV_ALPN NonEmpty ShortByteString
as) compare :: SPV_alpn -> SPV_alpn -> Ordering
`compare` (SPV_ALPN NonEmpty ShortByteString
bs) =
        (NonEmpty ShortByteString -> Int)
-> NonEmpty ShortByteString -> NonEmpty ShortByteString -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing NonEmpty ShortByteString -> Int
forall {t :: * -> *}. Foldable t => t ShortByteString -> Int
len NonEmpty ShortByteString
as NonEmpty ShortByteString
bs
        Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> (NonEmpty ShortByteString -> NonEmpty DnsText)
-> NonEmpty ShortByteString -> NonEmpty ShortByteString -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @(NonEmpty ShortByteString) @(NonEmpty DnsText)) NonEmpty ShortByteString
as NonEmpty ShortByteString
bs
      where
        len :: t ShortByteString -> Int
len t ShortByteString
xs = (Int -> ShortByteString -> Int) -> Int -> t ShortByteString -> Int
forall b a. (b -> a -> b) -> b -> t a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Int
a ShortByteString
x -> Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ShortByteString -> Int
SB.length ShortByteString
x) Int
0 t ShortByteString
xs

instance Presentable SPV_alpn where
    present :: SPV_alpn -> Builder -> Builder
present (SPV_ALPN NonEmpty ShortByteString
vs) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
ALPN (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Char
'=' (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty ShortByteString -> Builder -> Builder
presentSPVList NonEmpty ShortByteString
vs

instance KnownSVCParamValue SPV_alpn where
    spvKey :: forall b -> (b ~ SPV_alpn) => SVCParamKey
spvKey _ = SVCParamKey
ALPN
    encodeSPV :: forall r s. ErrorContext r => SPV_alpn -> SPut s r
encodeSPV (SPV_ALPN NonEmpty ShortByteString
vs) =
        SizedBuilder -> SPut s r
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s r) -> SizedBuilder -> SPut s r
forall a b. (a -> b) -> a -> b
$ (ShortByteString -> SizedBuilder)
-> NonEmpty ShortByteString -> SizedBuilder
forall m a. Monoid m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (ShortByteString -> SizedBuilder
mbShortByteStringLen8 (ShortByteString -> SizedBuilder)
-> (ShortByteString -> ShortByteString)
-> ShortByteString
-> SizedBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> ShortByteString
forall a b. Coercible a b => a -> b
coerce) NonEmpty ShortByteString
vs
    decodeSPV :: forall b -> (b ~ SPV_alpn) => Int -> SGet SVCParamValue
decodeSPV _ Int
len = do
        pos0 <- SGet Int
getPosition
        a <- getShortByteStringLen8
        pos1 <- getPosition
        let used = Int
pos1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
pos0
        as <- getVarWidthSequence getShortByteStringLen8 (len - used)
        pure $ SVCParamValue . SPV_ALPN $ a :| as

-- | The @no-default-alpn@ service parameter
-- ([RFC 9460 section 7.1](https://datatracker.ietf.org/doc/html/rfc9460#section-7.1))
-- — a value-less flag that suppresses the scheme's default ALPN
-- from the SVCB ALPN set.  Meaningful only alongside an explicit
-- 'SPV_alpn' that supplies a replacement protocol list.
data SPV_ndalpn = SPV_NDALPN
    deriving (SPV_ndalpn -> SPV_ndalpn -> Bool
(SPV_ndalpn -> SPV_ndalpn -> Bool)
-> (SPV_ndalpn -> SPV_ndalpn -> Bool) -> Eq SPV_ndalpn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_ndalpn -> SPV_ndalpn -> Bool
== :: SPV_ndalpn -> SPV_ndalpn -> Bool
$c/= :: SPV_ndalpn -> SPV_ndalpn -> Bool
/= :: SPV_ndalpn -> SPV_ndalpn -> Bool
Eq, Eq SPV_ndalpn
Eq SPV_ndalpn =>
(SPV_ndalpn -> SPV_ndalpn -> Ordering)
-> (SPV_ndalpn -> SPV_ndalpn -> Bool)
-> (SPV_ndalpn -> SPV_ndalpn -> Bool)
-> (SPV_ndalpn -> SPV_ndalpn -> Bool)
-> (SPV_ndalpn -> SPV_ndalpn -> Bool)
-> (SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn)
-> (SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn)
-> Ord SPV_ndalpn
SPV_ndalpn -> SPV_ndalpn -> Bool
SPV_ndalpn -> SPV_ndalpn -> Ordering
SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn
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 :: SPV_ndalpn -> SPV_ndalpn -> Ordering
compare :: SPV_ndalpn -> SPV_ndalpn -> Ordering
$c< :: SPV_ndalpn -> SPV_ndalpn -> Bool
< :: SPV_ndalpn -> SPV_ndalpn -> Bool
$c<= :: SPV_ndalpn -> SPV_ndalpn -> Bool
<= :: SPV_ndalpn -> SPV_ndalpn -> Bool
$c> :: SPV_ndalpn -> SPV_ndalpn -> Bool
> :: SPV_ndalpn -> SPV_ndalpn -> Bool
$c>= :: SPV_ndalpn -> SPV_ndalpn -> Bool
>= :: SPV_ndalpn -> SPV_ndalpn -> Bool
$cmax :: SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn
max :: SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn
$cmin :: SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn
min :: SPV_ndalpn -> SPV_ndalpn -> SPV_ndalpn
Ord, Int -> SPV_ndalpn -> ShowS
[SPV_ndalpn] -> ShowS
SPV_ndalpn -> String
(Int -> SPV_ndalpn -> ShowS)
-> (SPV_ndalpn -> String)
-> ([SPV_ndalpn] -> ShowS)
-> Show SPV_ndalpn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_ndalpn -> ShowS
showsPrec :: Int -> SPV_ndalpn -> ShowS
$cshow :: SPV_ndalpn -> String
show :: SPV_ndalpn -> String
$cshowList :: [SPV_ndalpn] -> ShowS
showList :: [SPV_ndalpn] -> ShowS
Show)

instance Presentable SPV_ndalpn where
    present :: SPV_ndalpn -> Builder -> Builder
present SPV_ndalpn
_ = SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
NODEFAULTALPN

instance KnownSVCParamValue SPV_ndalpn where
    spvKey :: forall b -> (b ~ SPV_ndalpn) => SVCParamKey
spvKey _ = SVCParamKey
NODEFAULTALPN
    encodeSPV :: forall r s. ErrorContext r => SPV_ndalpn -> SPut s r
encodeSPV SPV_ndalpn
_ = () -> SPutM s r ()
forall a. a -> SPutM s r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    decodeSPV :: forall b -> (b ~ SPV_ndalpn) => Int -> SGet SVCParamValue
decodeSPV _ Int
_ = SVCParamValue -> SGet SVCParamValue
forall a. a -> SGet a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SVCParamValue -> SGet SVCParamValue)
-> SVCParamValue -> SGet SVCParamValue
forall a b. (a -> b) -> a -> b
$ SPV_ndalpn -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue SPV_ndalpn
SPV_NDALPN

-- | The @port@ service parameter
-- ([RFC 9460 section 7.2](https://datatracker.ietf.org/doc/html/rfc9460#section-7.2))
-- — overrides the scheme's default TCP or UDP port for reaching
-- this service endpoint.
newtype SPV_port = SPV_PORT Word16
    deriving newtype (SPV_port -> SPV_port -> Bool
(SPV_port -> SPV_port -> Bool)
-> (SPV_port -> SPV_port -> Bool) -> Eq SPV_port
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_port -> SPV_port -> Bool
== :: SPV_port -> SPV_port -> Bool
$c/= :: SPV_port -> SPV_port -> Bool
/= :: SPV_port -> SPV_port -> Bool
Eq, Eq SPV_port
Eq SPV_port =>
(SPV_port -> SPV_port -> Ordering)
-> (SPV_port -> SPV_port -> Bool)
-> (SPV_port -> SPV_port -> Bool)
-> (SPV_port -> SPV_port -> Bool)
-> (SPV_port -> SPV_port -> Bool)
-> (SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> SPV_port)
-> Ord SPV_port
SPV_port -> SPV_port -> Bool
SPV_port -> SPV_port -> Ordering
SPV_port -> SPV_port -> SPV_port
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 :: SPV_port -> SPV_port -> Ordering
compare :: SPV_port -> SPV_port -> Ordering
$c< :: SPV_port -> SPV_port -> Bool
< :: SPV_port -> SPV_port -> Bool
$c<= :: SPV_port -> SPV_port -> Bool
<= :: SPV_port -> SPV_port -> Bool
$c> :: SPV_port -> SPV_port -> Bool
> :: SPV_port -> SPV_port -> Bool
$c>= :: SPV_port -> SPV_port -> Bool
>= :: SPV_port -> SPV_port -> Bool
$cmax :: SPV_port -> SPV_port -> SPV_port
max :: SPV_port -> SPV_port -> SPV_port
$cmin :: SPV_port -> SPV_port -> SPV_port
min :: SPV_port -> SPV_port -> SPV_port
Ord, Int -> SPV_port
SPV_port -> Int
SPV_port -> [SPV_port]
SPV_port -> SPV_port
SPV_port -> SPV_port -> [SPV_port]
SPV_port -> SPV_port -> SPV_port -> [SPV_port]
(SPV_port -> SPV_port)
-> (SPV_port -> SPV_port)
-> (Int -> SPV_port)
-> (SPV_port -> Int)
-> (SPV_port -> [SPV_port])
-> (SPV_port -> SPV_port -> [SPV_port])
-> (SPV_port -> SPV_port -> [SPV_port])
-> (SPV_port -> SPV_port -> SPV_port -> [SPV_port])
-> Enum SPV_port
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 :: SPV_port -> SPV_port
succ :: SPV_port -> SPV_port
$cpred :: SPV_port -> SPV_port
pred :: SPV_port -> SPV_port
$ctoEnum :: Int -> SPV_port
toEnum :: Int -> SPV_port
$cfromEnum :: SPV_port -> Int
fromEnum :: SPV_port -> Int
$cenumFrom :: SPV_port -> [SPV_port]
enumFrom :: SPV_port -> [SPV_port]
$cenumFromThen :: SPV_port -> SPV_port -> [SPV_port]
enumFromThen :: SPV_port -> SPV_port -> [SPV_port]
$cenumFromTo :: SPV_port -> SPV_port -> [SPV_port]
enumFromTo :: SPV_port -> SPV_port -> [SPV_port]
$cenumFromThenTo :: SPV_port -> SPV_port -> SPV_port -> [SPV_port]
enumFromThenTo :: SPV_port -> SPV_port -> SPV_port -> [SPV_port]
Enum, SPV_port
SPV_port -> SPV_port -> Bounded SPV_port
forall a. a -> a -> Bounded a
$cminBound :: SPV_port
minBound :: SPV_port
$cmaxBound :: SPV_port
maxBound :: SPV_port
Bounded, Integer -> SPV_port
SPV_port -> SPV_port
SPV_port -> SPV_port -> SPV_port
(SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port)
-> (SPV_port -> SPV_port)
-> (SPV_port -> SPV_port)
-> (Integer -> SPV_port)
-> Num SPV_port
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: SPV_port -> SPV_port -> SPV_port
+ :: SPV_port -> SPV_port -> SPV_port
$c- :: SPV_port -> SPV_port -> SPV_port
- :: SPV_port -> SPV_port -> SPV_port
$c* :: SPV_port -> SPV_port -> SPV_port
* :: SPV_port -> SPV_port -> SPV_port
$cnegate :: SPV_port -> SPV_port
negate :: SPV_port -> SPV_port
$cabs :: SPV_port -> SPV_port
abs :: SPV_port -> SPV_port
$csignum :: SPV_port -> SPV_port
signum :: SPV_port -> SPV_port
$cfromInteger :: Integer -> SPV_port
fromInteger :: Integer -> SPV_port
Num, Num SPV_port
Ord SPV_port
(Num SPV_port, Ord SPV_port) =>
(SPV_port -> Rational) -> Real SPV_port
SPV_port -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
$ctoRational :: SPV_port -> Rational
toRational :: SPV_port -> Rational
Real, Enum SPV_port
Real SPV_port
(Real SPV_port, Enum SPV_port) =>
(SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> SPV_port)
-> (SPV_port -> SPV_port -> (SPV_port, SPV_port))
-> (SPV_port -> SPV_port -> (SPV_port, SPV_port))
-> (SPV_port -> Integer)
-> Integral SPV_port
SPV_port -> Integer
SPV_port -> SPV_port -> (SPV_port, SPV_port)
SPV_port -> SPV_port -> SPV_port
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: SPV_port -> SPV_port -> SPV_port
quot :: SPV_port -> SPV_port -> SPV_port
$crem :: SPV_port -> SPV_port -> SPV_port
rem :: SPV_port -> SPV_port -> SPV_port
$cdiv :: SPV_port -> SPV_port -> SPV_port
div :: SPV_port -> SPV_port -> SPV_port
$cmod :: SPV_port -> SPV_port -> SPV_port
mod :: SPV_port -> SPV_port -> SPV_port
$cquotRem :: SPV_port -> SPV_port -> (SPV_port, SPV_port)
quotRem :: SPV_port -> SPV_port -> (SPV_port, SPV_port)
$cdivMod :: SPV_port -> SPV_port -> (SPV_port, SPV_port)
divMod :: SPV_port -> SPV_port -> (SPV_port, SPV_port)
$ctoInteger :: SPV_port -> Integer
toInteger :: SPV_port -> Integer
Integral, Int -> SPV_port -> ShowS
[SPV_port] -> ShowS
SPV_port -> String
(Int -> SPV_port -> ShowS)
-> (SPV_port -> String) -> ([SPV_port] -> ShowS) -> Show SPV_port
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_port -> ShowS
showsPrec :: Int -> SPV_port -> ShowS
$cshow :: SPV_port -> String
show :: SPV_port -> String
$cshowList :: [SPV_port] -> ShowS
showList :: [SPV_port] -> ShowS
Show, ReadPrec [SPV_port]
ReadPrec SPV_port
Int -> ReadS SPV_port
ReadS [SPV_port]
(Int -> ReadS SPV_port)
-> ReadS [SPV_port]
-> ReadPrec SPV_port
-> ReadPrec [SPV_port]
-> Read SPV_port
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS SPV_port
readsPrec :: Int -> ReadS SPV_port
$creadList :: ReadS [SPV_port]
readList :: ReadS [SPV_port]
$creadPrec :: ReadPrec SPV_port
readPrec :: ReadPrec SPV_port
$creadListPrec :: ReadPrec [SPV_port]
readListPrec :: ReadPrec [SPV_port]
Read)

instance Presentable SPV_port where
    present :: SPV_port -> Builder -> Builder
present (SPV_PORT Word16
port) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
PORT
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Word16 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
'=' Word16
port

instance KnownSVCParamValue SPV_port where
    spvKey :: forall b -> (b ~ SPV_port) => SVCParamKey
spvKey _ = SVCParamKey
PORT
    encodeSPV :: forall r s. ErrorContext r => SPV_port -> SPut s r
encodeSPV = Word16 -> SPut s r
forall r s. ErrorContext r => Word16 -> SPut s r
put16 (Word16 -> SPut s r)
-> (SPV_port -> Word16) -> SPV_port -> SPut s r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SPV_port -> Word16
forall a b. Coercible a b => a -> b
coerce
    decodeSPV :: forall b -> (b ~ SPV_port) => Int -> SGet SVCParamValue
decodeSPV _ Int
_ = SPV_port -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue (SPV_port -> SVCParamValue)
-> (Word16 -> SPV_port) -> Word16 -> SVCParamValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> SPV_port
SPV_PORT (Word16 -> SVCParamValue) -> SGet Word16 -> SGet SVCParamValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SGet Word16
get16

-- | The @ipv4hint@ service parameter
-- ([RFC 9460 section 7.3](https://datatracker.ietf.org/doc/html/rfc9460#section-7.3))
-- — a non-empty list of IPv4 addresses for this service endpoint
-- that a client may use to start a connection in parallel with
-- an authoritative @A@ lookup.  Hints are advisory; clients
-- should still validate them against authoritative address
-- records when they arrive.
newtype SPV_ipv4hint = SPV_IPV4HINT (NonEmpty IPv4)
    deriving (SPV_ipv4hint -> SPV_ipv4hint -> Bool
(SPV_ipv4hint -> SPV_ipv4hint -> Bool)
-> (SPV_ipv4hint -> SPV_ipv4hint -> Bool) -> Eq SPV_ipv4hint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_ipv4hint -> SPV_ipv4hint -> Bool
== :: SPV_ipv4hint -> SPV_ipv4hint -> Bool
$c/= :: SPV_ipv4hint -> SPV_ipv4hint -> Bool
/= :: SPV_ipv4hint -> SPV_ipv4hint -> Bool
Eq)

instance Show SPV_ipv4hint where
    showsPrec :: Int -> SPV_ipv4hint -> ShowS
showsPrec Int
p (SPV_IPV4HINT NonEmpty IPv4
ips) = Int -> ShowS -> ShowS
showsP Int
p (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString String
"SPV_IPV4HINT "
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty String -> ShowS
forall a. Show a => a -> ShowS
shows' ((IPv4 -> String) -> NonEmpty IPv4 -> NonEmpty String
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IPv4 -> String
forall a. Show a => a -> String
show NonEmpty IPv4
ips)

instance Ord SPV_ipv4hint where
    compare :: SPV_ipv4hint -> SPV_ipv4hint -> Ordering
compare (SPV_IPV4HINT NonEmpty IPv4
a) (SPV_IPV4HINT NonEmpty IPv4
b) =
        (NonEmpty IPv4 -> Int)
-> NonEmpty IPv4 -> NonEmpty IPv4 -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing NonEmpty IPv4 -> Int
forall a. NonEmpty a -> Int
NE.length NonEmpty IPv4
a NonEmpty IPv4
b Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> NonEmpty IPv4 -> NonEmpty IPv4 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare NonEmpty IPv4
a NonEmpty IPv4
b

instance Presentable SPV_ipv4hint where
    present :: SPV_ipv4hint -> Builder -> Builder
present (SPV_IPV4HINT (IPv4
a :| [IPv4]
as)) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
IPV4HINT
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IPv4 -> Builder -> Builder
pfst IPv4
a
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> [IPv4] -> Builder) -> [IPv4] -> Builder -> Builder
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((IPv4 -> Builder -> Builder) -> Builder -> [IPv4] -> Builder
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr IPv4 -> Builder -> Builder
pnxt) [IPv4]
as
      where
        pfst :: IPv4 -> Builder -> Builder
pfst = Char -> IPv4 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
'='
        pnxt :: IPv4 -> Builder -> Builder
pnxt = Char -> IPv4 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
','

instance KnownSVCParamValue SPV_ipv4hint where
    spvKey :: forall b -> (b ~ SPV_ipv4hint) => SVCParamKey
spvKey _ = SVCParamKey
IPV4HINT
    encodeSPV :: forall r s. ErrorContext r => SPV_ipv4hint -> SPut s r
encodeSPV (SPV_IPV4HINT NonEmpty IPv4
ips) = SizedBuilder -> SPut s r
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s r) -> SizedBuilder -> SPut s r
forall a b. (a -> b) -> a -> b
$ (IPv4 -> SizedBuilder) -> NonEmpty IPv4 -> SizedBuilder
forall m a. Monoid m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap IPv4 -> SizedBuilder
mbIPv4 NonEmpty IPv4
ips
    decodeSPV :: forall b -> (b ~ SPV_ipv4hint) => Int -> SGet SVCParamValue
decodeSPV _ Int
len = do
        ip  <- SGet IPv4
getIPv4
        ips <- getFixedWidthSequence 4 getIPv4 (len - 4)
        return $ SVCParamValue $ SPV_IPV4HINT (ip :| ips)

-- | The @ipv6hint@ service parameter
-- ([RFC 9460 section 7.3](https://datatracker.ietf.org/doc/html/rfc9460#section-7.3))
-- — the IPv6 counterpart of 'SPV_ipv4hint': a non-empty list of
-- IPv6 addresses to try in parallel with the authoritative
-- @AAAA@ lookup.
newtype SPV_ipv6hint = SPV_IPV6HINT (NonEmpty IPv6)
    deriving (SPV_ipv6hint -> SPV_ipv6hint -> Bool
(SPV_ipv6hint -> SPV_ipv6hint -> Bool)
-> (SPV_ipv6hint -> SPV_ipv6hint -> Bool) -> Eq SPV_ipv6hint
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_ipv6hint -> SPV_ipv6hint -> Bool
== :: SPV_ipv6hint -> SPV_ipv6hint -> Bool
$c/= :: SPV_ipv6hint -> SPV_ipv6hint -> Bool
/= :: SPV_ipv6hint -> SPV_ipv6hint -> Bool
Eq)

instance Show SPV_ipv6hint where
    showsPrec :: Int -> SPV_ipv6hint -> ShowS
showsPrec Int
p (SPV_IPV6HINT NonEmpty IPv6
ips) = Int -> ShowS -> ShowS
showsP Int
p (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
        String -> ShowS
showString String
"SPV_IPV6HINT "
        ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty String -> ShowS
forall a. Show a => a -> ShowS
shows' ((IPv6 -> String) -> NonEmpty IPv6 -> NonEmpty String
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IPv6 -> String
forall a. Show a => a -> String
show NonEmpty IPv6
ips)

instance Ord SPV_ipv6hint where
    compare :: SPV_ipv6hint -> SPV_ipv6hint -> Ordering
compare (SPV_IPV6HINT NonEmpty IPv6
a) (SPV_IPV6HINT NonEmpty IPv6
b) =
        (NonEmpty IPv6 -> Int)
-> NonEmpty IPv6 -> NonEmpty IPv6 -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing NonEmpty IPv6 -> Int
forall a. NonEmpty a -> Int
NE.length NonEmpty IPv6
a NonEmpty IPv6
b Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> NonEmpty IPv6 -> NonEmpty IPv6 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare NonEmpty IPv6
a NonEmpty IPv6
b

instance Presentable SPV_ipv6hint where
    present :: SPV_ipv6hint -> Builder -> Builder
present (SPV_IPV6HINT (IPv6
a :| [IPv6]
as)) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
IPV6HINT
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IPv6 -> Builder -> Builder
pfst IPv6
a
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> [IPv6] -> Builder) -> [IPv6] -> Builder -> Builder
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((IPv6 -> Builder -> Builder) -> Builder -> [IPv6] -> Builder
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr IPv6 -> Builder -> Builder
pnxt) [IPv6]
as
      where
        pfst :: IPv6 -> Builder -> Builder
pfst = Char -> IPv6 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
'='
        pnxt :: IPv6 -> Builder -> Builder
pnxt = Char -> IPv6 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
','

instance KnownSVCParamValue SPV_ipv6hint where
    spvKey :: forall b -> (b ~ SPV_ipv6hint) => SVCParamKey
spvKey _ = SVCParamKey
IPV6HINT
    encodeSPV :: forall r s. ErrorContext r => SPV_ipv6hint -> SPut s r
encodeSPV (SPV_IPV6HINT NonEmpty IPv6
ips) = SizedBuilder -> SPut s r
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s r) -> SizedBuilder -> SPut s r
forall a b. (a -> b) -> a -> b
$ (IPv6 -> SizedBuilder) -> NonEmpty IPv6 -> SizedBuilder
forall m a. Monoid m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap IPv6 -> SizedBuilder
mbIPv6 NonEmpty IPv6
ips
    decodeSPV :: forall b -> (b ~ SPV_ipv6hint) => Int -> SGet SVCParamValue
decodeSPV _ Int
len = do
        ip  <- SGet IPv6
getIPv6
        ips <- getFixedWidthSequence 16 getIPv6 (len - 16)
        return $ SVCParamValue $ SPV_IPV6HINT (ip :| ips)

-- | The @ech@ service parameter
-- ([RFC9848, Section 3](https://datatracker.ietf.org/doc/html/rfc9848#section-3))
-- — an Encrypted Client Hello (ECH) configuration list.
-- Presented as a base64-encoded value.
newtype SPV_ech = SPV_ECH ShortByteString
    deriving (SPV_ech -> SPV_ech -> Bool
(SPV_ech -> SPV_ech -> Bool)
-> (SPV_ech -> SPV_ech -> Bool) -> Eq SPV_ech
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_ech -> SPV_ech -> Bool
== :: SPV_ech -> SPV_ech -> Bool
$c/= :: SPV_ech -> SPV_ech -> Bool
/= :: SPV_ech -> SPV_ech -> Bool
Eq, Int -> SPV_ech -> ShowS
[SPV_ech] -> ShowS
SPV_ech -> String
(Int -> SPV_ech -> ShowS)
-> (SPV_ech -> String) -> ([SPV_ech] -> ShowS) -> Show SPV_ech
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_ech -> ShowS
showsPrec :: Int -> SPV_ech -> ShowS
$cshow :: SPV_ech -> String
show :: SPV_ech -> String
$cshowList :: [SPV_ech] -> ShowS
showList :: [SPV_ech] -> ShowS
Show)

instance Ord SPV_ech where
    compare :: SPV_ech -> SPV_ech -> Ordering
compare = SPV_ech -> SPV_ech -> Ordering
forall a. Coercible a ShortByteString => a -> a -> Ordering
dnsTextCmp

instance Presentable SPV_ech where
    present :: SPV_ech -> Builder -> Builder
present (SPV_ECH ShortByteString
c) = SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
ECH (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep @Bytes64 Char
'=' (ShortByteString -> Bytes64
forall a b. Coercible a b => a -> b
coerce ShortByteString
c)

instance KnownSVCParamValue SPV_ech where
    spvKey :: forall b -> (b ~ SPV_ech) => SVCParamKey
spvKey _ = SVCParamKey
ECH
    encodeSPV :: forall r s. ErrorContext r => SPV_ech -> SPut s r
encodeSPV (SPV_ECH ShortByteString
c) = ShortByteString -> SPut s r
forall r s. ErrorContext r => ShortByteString -> SPut s r
putShortByteString (ShortByteString -> SPut s r) -> ShortByteString -> SPut s r
forall a b. (a -> b) -> a -> b
$ ShortByteString -> ShortByteString
forall a b. Coercible a b => a -> b
coerce ShortByteString
c
    decodeSPV :: forall b -> (b ~ SPV_ech) => Int -> SGet SVCParamValue
decodeSPV _ Int
0 = String -> SGet SVCParamValue
forall a. String -> SGet a
failSGet String
"Invalid empty 'ech' ParamKey value"
    decodeSPV _ Int
len
        | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
4 = String -> SGet SVCParamValue
forall a. String -> SGet a
failSGet String
"'ech' ParamKey value too short"
        | Bool
otherwise = SPV_ech -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue (SPV_ech -> SVCParamValue)
-> (ShortByteString -> SPV_ech) -> ShortByteString -> SVCParamValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortByteString -> SPV_ech
SPV_ECH (ShortByteString -> SVCParamValue)
-> SGet ShortByteString -> SGet SVCParamValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> SGet ShortByteString
getShortNByteString Int
len

-- | The @dohpath@ service parameter
-- ([RFC 9461](https://datatracker.ietf.org/doc/html/rfc9461#name-new-svcparamkey-dohpath))
-- — a URI template (UTF-8) advertising the DNS-over-HTTPS
-- endpoint at this service.  Typically seen on resolver-discovery
-- answers to queries for @_dns.resolver.arpa@ or on explicit
-- queries to a specific operator's resolver.
newtype SPV_dohpath = SPV_DOHPATH T.Text
    deriving (SPV_dohpath -> SPV_dohpath -> Bool
(SPV_dohpath -> SPV_dohpath -> Bool)
-> (SPV_dohpath -> SPV_dohpath -> Bool) -> Eq SPV_dohpath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_dohpath -> SPV_dohpath -> Bool
== :: SPV_dohpath -> SPV_dohpath -> Bool
$c/= :: SPV_dohpath -> SPV_dohpath -> Bool
/= :: SPV_dohpath -> SPV_dohpath -> Bool
Eq, Int -> SPV_dohpath -> ShowS
[SPV_dohpath] -> ShowS
SPV_dohpath -> String
(Int -> SPV_dohpath -> ShowS)
-> (SPV_dohpath -> String)
-> ([SPV_dohpath] -> ShowS)
-> Show SPV_dohpath
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_dohpath -> ShowS
showsPrec :: Int -> SPV_dohpath -> ShowS
$cshow :: SPV_dohpath -> String
show :: SPV_dohpath -> String
$cshowList :: [SPV_dohpath] -> ShowS
showList :: [SPV_dohpath] -> ShowS
Show)

instance Ord SPV_dohpath where
    compare :: SPV_dohpath -> SPV_dohpath -> Ordering
compare (SPV_DOHPATH Text
a) (SPV_DOHPATH Text
b) =
        (Text -> Int) -> Text -> Text -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Text -> Int
T.lengthWord8 Text
a Text
b
        Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
a Text
b

instance Presentable SPV_dohpath where
    present :: SPV_dohpath -> Builder -> Builder
present (SPV_DOHPATH Text
uri) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
DOHPATH (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep @DnsUtf8Text Char
'=' (Text -> DnsUtf8Text
forall a b. Coercible a b => a -> b
coerce Text
uri)

instance KnownSVCParamValue SPV_dohpath where
    spvKey :: forall b -> (b ~ SPV_dohpath) => SVCParamKey
spvKey _ = SVCParamKey
DOHPATH
    encodeSPV :: forall r s. ErrorContext r => SPV_dohpath -> SPut s r
encodeSPV (SPV_DOHPATH Text
uri) = Text -> SPut s r
forall r s. ErrorContext r => Text -> SPut s r
putUtf8Text Text
uri
    decodeSPV :: forall b -> (b ~ SPV_dohpath) => Int -> SGet SVCParamValue
decodeSPV _ = SPV_dohpath -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue (SPV_dohpath -> SVCParamValue)
-> (Text -> SPV_dohpath) -> Text -> SVCParamValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> SPV_dohpath
SPV_DOHPATH (Text -> SVCParamValue)
-> (Int -> SGet Text) -> Int -> SGet SVCParamValue
forall (m :: * -> *) b c a.
Functor m =>
(b -> c) -> (a -> m b) -> a -> m c
<.> Int -> SGet Text
getUtf8Text

-- | The @docpath@ service parameter
-- ([RFC 9953 section 8.2](https://datatracker.ietf.org/doc/html/rfc9953#section-8.2))
-- — the absolute path to the DNS-over-CoAP (DoC) resource at this
-- service endpoint, represented as a list of path segments.  An
-- empty list denotes the root path @\"/\"@ (on the wire: a
-- zero-length SvcParamValue).
--
-- Each segment is 1..255 octets per the RFC ABNF; the wire-form
-- decoder rejects zero-length segments.  Presentation form is a
-- comma-separated list of segments using the standard RFC 9460
-- Appendix A.1 quoting and escaping rules, identical to those of
-- 'SPV_alpn'.
newtype SPV_docpath = SPV_DOCPATH [ShortByteString]
    deriving (SPV_docpath -> SPV_docpath -> Bool
(SPV_docpath -> SPV_docpath -> Bool)
-> (SPV_docpath -> SPV_docpath -> Bool) -> Eq SPV_docpath
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_docpath -> SPV_docpath -> Bool
== :: SPV_docpath -> SPV_docpath -> Bool
$c/= :: SPV_docpath -> SPV_docpath -> Bool
/= :: SPV_docpath -> SPV_docpath -> Bool
Eq, Int -> SPV_docpath -> ShowS
[SPV_docpath] -> ShowS
SPV_docpath -> String
(Int -> SPV_docpath -> ShowS)
-> (SPV_docpath -> String)
-> ([SPV_docpath] -> ShowS)
-> Show SPV_docpath
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_docpath -> ShowS
showsPrec :: Int -> SPV_docpath -> ShowS
$cshow :: SPV_docpath -> String
show :: SPV_docpath -> String
$cshowList :: [SPV_docpath] -> ShowS
showList :: [SPV_docpath] -> ShowS
Show)

-- | Wire-form canonical order: by total wire length first, then
-- by the segment-list 'DnsText' ordering.
instance Ord SPV_docpath where
    (SPV_DOCPATH [ShortByteString]
as) compare :: SPV_docpath -> SPV_docpath -> Ordering
`compare` (SPV_DOCPATH [ShortByteString]
bs) =
        ([ShortByteString] -> Int)
-> [ShortByteString] -> [ShortByteString] -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing [ShortByteString] -> Int
wireLen [ShortByteString]
as [ShortByteString]
bs
        Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> ([ShortByteString] -> [DnsText])
-> [ShortByteString] -> [ShortByteString] -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @[ShortByteString] @[DnsText]) [ShortByteString]
as [ShortByteString]
bs
      where
        wireLen :: [ShortByteString] -> Int
wireLen = (Int -> ShortByteString -> Int) -> Int -> [ShortByteString] -> Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Int
a ShortByteString
x -> Int
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ShortByteString -> Int
SB.length ShortByteString
x) Int
0

instance Presentable SPV_docpath where
    present :: SPV_docpath -> Builder -> Builder
present (SPV_DOCPATH [ShortByteString]
vs) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
DOCPATH (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present Char
'=' (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ShortByteString] -> Builder -> Builder
presentCSVList [ShortByteString]
vs

instance KnownSVCParamValue SPV_docpath where
    spvKey :: forall b -> (b ~ SPV_docpath) => SVCParamKey
spvKey _ = SVCParamKey
DOCPATH
    encodeSPV :: forall r s. ErrorContext r => SPV_docpath -> SPut s r
encodeSPV (SPV_DOCPATH [ShortByteString]
vs) =
        SizedBuilder -> SPut s r
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s r) -> SizedBuilder -> SPut s r
forall a b. (a -> b) -> a -> b
$ (ShortByteString -> SizedBuilder)
-> [ShortByteString] -> SizedBuilder
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap ShortByteString -> SizedBuilder
mbShortByteStringLen8 [ShortByteString]
vs
    decodeSPV :: forall b -> (b ~ SPV_docpath) => Int -> SGet SVCParamValue
decodeSPV _ Int
len = do
        vs <- SGet ShortByteString -> Int -> SGet [ShortByteString]
forall a. SGet a -> Int -> SGet [a]
getVarWidthSequence SGet ShortByteString
segment Int
len
        pure $ SVCParamValue $ SPV_DOCPATH vs
      where
        segment :: SGet ShortByteString
segment = do
            seg <- SGet ShortByteString
getShortByteStringLen8
            when (SB.null seg) $ failSGet "Empty docpath segment"
            pure seg

-- | The @tls-supported-groups@ service parameter
-- ([draft-ietf-tls-key-share-prediction-04 section 5](https://datatracker.ietf.org/doc/html/draft-ietf-tls-key-share-prediction-04#section-5))
-- — a non-empty list of TLS Named Group codepoints (the
-- [IANA TLS Supported Groups registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8))
-- that the service supports.  Clients can use this hint to
-- predict an acceptable key share, reducing the chance of a
-- HelloRetryRequest round-trip.
--
-- The wire form is a non-empty sequence of 16-bit codepoints in
-- network byte order; the decoder rejects an empty value.  The
-- presentation form is a comma-separated list of decimal
-- integers and forbids zone-file escape sequences (per the
-- draft).  Duplicates are flagged as a syntax error by the
-- specification but are not currently rejected by either the
-- encoder or the decoder — callers are expected to feed in a
-- duplicate-free list, in their preferred order (the spec does
-- not impose canonical ordering on the wire).
newtype SPV_tlsgroups = SPV_TLSGROUPS (NonEmpty Word16)
    deriving (SPV_tlsgroups -> SPV_tlsgroups -> Bool
(SPV_tlsgroups -> SPV_tlsgroups -> Bool)
-> (SPV_tlsgroups -> SPV_tlsgroups -> Bool) -> Eq SPV_tlsgroups
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_tlsgroups -> SPV_tlsgroups -> Bool
== :: SPV_tlsgroups -> SPV_tlsgroups -> Bool
$c/= :: SPV_tlsgroups -> SPV_tlsgroups -> Bool
/= :: SPV_tlsgroups -> SPV_tlsgroups -> Bool
Eq, Int -> SPV_tlsgroups -> ShowS
[SPV_tlsgroups] -> ShowS
SPV_tlsgroups -> String
(Int -> SPV_tlsgroups -> ShowS)
-> (SPV_tlsgroups -> String)
-> ([SPV_tlsgroups] -> ShowS)
-> Show SPV_tlsgroups
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_tlsgroups -> ShowS
showsPrec :: Int -> SPV_tlsgroups -> ShowS
$cshow :: SPV_tlsgroups -> String
show :: SPV_tlsgroups -> String
$cshowList :: [SPV_tlsgroups] -> ShowS
showList :: [SPV_tlsgroups] -> ShowS
Show)

-- | Wire-form canonical order: by length first, then elementwise.
instance Ord SPV_tlsgroups where
    (SPV_TLSGROUPS NonEmpty Word16
as) compare :: SPV_tlsgroups -> SPV_tlsgroups -> Ordering
`compare` (SPV_TLSGROUPS NonEmpty Word16
bs) =
        (NonEmpty Word16 -> Int)
-> NonEmpty Word16 -> NonEmpty Word16 -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing NonEmpty Word16 -> Int
forall a. NonEmpty a -> Int
NE.length NonEmpty Word16
as NonEmpty Word16
bs Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> NonEmpty Word16 -> NonEmpty Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare NonEmpty Word16
as NonEmpty Word16
bs

instance Presentable SPV_tlsgroups where
    present :: SPV_tlsgroups -> Builder -> Builder
present (SPV_TLSGROUPS (Word16
g :| [Word16]
gs)) =
        SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
TLSGROUPS
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Builder -> Builder
pfst Word16
g
        (Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> [Word16] -> Builder) -> [Word16] -> Builder -> Builder
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Word16 -> Builder -> Builder) -> Builder -> [Word16] -> Builder
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Word16 -> Builder -> Builder
pnxt) [Word16]
gs
      where
        pfst :: Word16 -> Builder -> Builder
pfst = Char -> Word16 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
'='
        pnxt :: Word16 -> Builder -> Builder
pnxt = Char -> Word16 -> Builder -> Builder
forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep Char
','

instance KnownSVCParamValue SPV_tlsgroups where
    spvKey :: forall b -> (b ~ SPV_tlsgroups) => SVCParamKey
spvKey _ = SVCParamKey
TLSGROUPS
    encodeSPV :: forall r s. ErrorContext r => SPV_tlsgroups -> SPut s r
encodeSPV (SPV_TLSGROUPS NonEmpty Word16
gs) = SizedBuilder -> SPut s r
forall r s. ErrorContext r => SizedBuilder -> SPut s r
putSizedBuilder (SizedBuilder -> SPut s r) -> SizedBuilder -> SPut s r
forall a b. (a -> b) -> a -> b
$ (Word16 -> SizedBuilder) -> NonEmpty Word16 -> SizedBuilder
forall m a. Monoid m => (a -> m) -> NonEmpty a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Word16 -> SizedBuilder
mbWord16 NonEmpty Word16
gs
    decodeSPV :: forall b -> (b ~ SPV_tlsgroups) => Int -> SGet SVCParamValue
decodeSPV _ Int
len = do
        g  <- SGet Word16
get16
        gs <- getFixedWidthSequence 2 get16 (len - 2)
        pure $ SVCParamValue $ SPV_TLSGROUPS (g :| gs)

-- | The @pvd@ service parameter
-- ([draft-ietf-intarea-proxy-config-14 section 7.5](https://datatracker.ietf.org/doc/html/draft-ietf-intarea-proxy-config-14#section-7.5))
-- — a value-less flag that announces the host supports
-- Provisioning Domain discovery via the well-known PvD URI.  Its
-- presence in an SVCB or HTTPS RR signals that a client MAY
-- fetch PvD Additional Information from
-- @https:\/\/host\/.well-known\/pvd@.  Per the draft, the wire
-- value MUST be empty; the presentation form is just the bare
-- key name with no @\'=\'@.
data SPV_pvd = SPV_PVD
    deriving (SPV_pvd -> SPV_pvd -> Bool
(SPV_pvd -> SPV_pvd -> Bool)
-> (SPV_pvd -> SPV_pvd -> Bool) -> Eq SPV_pvd
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SPV_pvd -> SPV_pvd -> Bool
== :: SPV_pvd -> SPV_pvd -> Bool
$c/= :: SPV_pvd -> SPV_pvd -> Bool
/= :: SPV_pvd -> SPV_pvd -> Bool
Eq, Eq SPV_pvd
Eq SPV_pvd =>
(SPV_pvd -> SPV_pvd -> Ordering)
-> (SPV_pvd -> SPV_pvd -> Bool)
-> (SPV_pvd -> SPV_pvd -> Bool)
-> (SPV_pvd -> SPV_pvd -> Bool)
-> (SPV_pvd -> SPV_pvd -> Bool)
-> (SPV_pvd -> SPV_pvd -> SPV_pvd)
-> (SPV_pvd -> SPV_pvd -> SPV_pvd)
-> Ord SPV_pvd
SPV_pvd -> SPV_pvd -> Bool
SPV_pvd -> SPV_pvd -> Ordering
SPV_pvd -> SPV_pvd -> SPV_pvd
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 :: SPV_pvd -> SPV_pvd -> Ordering
compare :: SPV_pvd -> SPV_pvd -> Ordering
$c< :: SPV_pvd -> SPV_pvd -> Bool
< :: SPV_pvd -> SPV_pvd -> Bool
$c<= :: SPV_pvd -> SPV_pvd -> Bool
<= :: SPV_pvd -> SPV_pvd -> Bool
$c> :: SPV_pvd -> SPV_pvd -> Bool
> :: SPV_pvd -> SPV_pvd -> Bool
$c>= :: SPV_pvd -> SPV_pvd -> Bool
>= :: SPV_pvd -> SPV_pvd -> Bool
$cmax :: SPV_pvd -> SPV_pvd -> SPV_pvd
max :: SPV_pvd -> SPV_pvd -> SPV_pvd
$cmin :: SPV_pvd -> SPV_pvd -> SPV_pvd
min :: SPV_pvd -> SPV_pvd -> SPV_pvd
Ord, Int -> SPV_pvd -> ShowS
[SPV_pvd] -> ShowS
SPV_pvd -> String
(Int -> SPV_pvd -> ShowS)
-> (SPV_pvd -> String) -> ([SPV_pvd] -> ShowS) -> Show SPV_pvd
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SPV_pvd -> ShowS
showsPrec :: Int -> SPV_pvd -> ShowS
$cshow :: SPV_pvd -> String
show :: SPV_pvd -> String
$cshowList :: [SPV_pvd] -> ShowS
showList :: [SPV_pvd] -> ShowS
Show)

instance Presentable SPV_pvd where
    present :: SPV_pvd -> Builder -> Builder
present SPV_pvd
_ = SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present SVCParamKey
PVD

instance KnownSVCParamValue SPV_pvd where
    spvKey :: forall b -> (b ~ SPV_pvd) => SVCParamKey
spvKey _ = SVCParamKey
PVD
    encodeSPV :: forall r s. ErrorContext r => SPV_pvd -> SPut s r
encodeSPV SPV_pvd
_ = () -> SPutM s r ()
forall a. a -> SPutM s r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    decodeSPV :: forall b -> (b ~ SPV_pvd) => Int -> SGet SVCParamValue
decodeSPV _ Int
_ = SVCParamValue -> SGet SVCParamValue
forall a. a -> SGet a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SVCParamValue -> SGet SVCParamValue)
-> SVCParamValue -> SGet SVCParamValue
forall a b. (a -> b) -> a -> b
$ SPV_pvd -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue SPV_pvd
SPV_PVD