module Net.DNSBase.RData.SVCB.SVCParamValue
( KnownSVCParamValue(..)
, SVCParamValue(..)
, fromSPV
, serviceParamKey
, OpaqueSPV(..)
, opaqueSPV
, toOpaqueSPV
) where
import qualified Data.ByteString.Short as SB
import Net.DNSBase.Internal.Util
import Net.DNSBase.Decode.State
import Net.DNSBase.Encode.State
import Net.DNSBase.Nat16
import Net.DNSBase.Present
import Net.DNSBase.RData.SVCB.SVCParamKey
import Net.DNSBase.Text
class (Typeable a, Eq a, Ord a, Show a, Presentable a) => KnownSVCParamValue a where
spvKey :: forall b -> b ~ a => SVCParamKey
spvKeyPres :: forall b -> b ~ a => Builder -> Builder
encodeSPV :: forall r s. ErrorContext r => a -> SPut s r
decodeSPV :: forall b -> b ~ a => Int -> SGet SVCParamValue
spvKeyPres _ = SVCParamKey -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present (spvKey a)
data SVCParamValue = forall a. KnownSVCParamValue a => SVCParamValue a
fromSPV :: forall a. KnownSVCParamValue a => SVCParamValue -> Maybe a
fromSPV :: forall a. KnownSVCParamValue a => SVCParamValue -> Maybe a
fromSPV (SVCParamValue a
a) = a -> Maybe a
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
a
svcParamValueKey :: SVCParamValue -> SVCParamKey
svcParamValueKey :: SVCParamValue -> SVCParamKey
svcParamValueKey (SVCParamValue (a
_ :: t)) = spvKey t
{-# INLINE svcParamValueKey #-}
spvEncode :: ErrorContext r => SVCParamValue -> SPut s r
spvEncode :: forall r s. ErrorContext r => SVCParamValue -> SPut s r
spvEncode (SVCParamValue a
a) = a -> SPut s r
forall a r s.
(KnownSVCParamValue a, ErrorContext r) =>
a -> SPut s r
forall r s. ErrorContext r => a -> SPut s r
encodeSPV a
a
serviceParamKey :: SVCParamValue -> SVCParamKey
serviceParamKey :: SVCParamValue -> SVCParamKey
serviceParamKey (SVCParamValue (a
_ :: t)) = spvKey t
instance Eq SVCParamValue where
(SVCParamValue (a
_a :: a)) == :: SVCParamValue -> SVCParamValue -> Bool
== (SVCParamValue (a
_b :: b))
| spvKey a SVCParamKey -> SVCParamKey -> Bool
forall a. Eq a => a -> a -> Bool
/= spvKey b = Bool
False
| Just a :~: a
Refl <- teq a b = a
_a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a
_b
| Bool
otherwise = Bool
False
instance Ord SVCParamValue where
compare :: SVCParamValue -> SVCParamValue -> Ordering
compare sa :: SVCParamValue
sa@(SVCParamValue (a
_a :: a)) sb :: SVCParamValue
sb@(SVCParamValue (a
_b :: b)) =
SVCParamKey -> SVCParamKey -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (spvKey a) (spvKey b)
Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> if | Just a :~: a
Refl <- teq a b -> a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
_a a
a
_b
| SVCParamKey -> SVCParamValue -> Bool
isOpaque (spvKey a) SVCParamValue
sa -> Ordering
GT
| SVCParamKey -> SVCParamValue -> Bool
isOpaque (spvKey b) SVCParamValue
sb -> Ordering
LT
| Bool
otherwise -> Either (EncodeErr (Maybe ())) SVCParamValue
-> Either (EncodeErr (Maybe ())) SVCParamValue -> Ordering
forall {a} {a} {a}.
(Ord a, Show a, Show a) =>
Either a a -> Either a a -> Ordering
ocmp (SVCParamValue -> Either (EncodeErr (Maybe ())) SVCParamValue
toOpaqueSPV SVCParamValue
sa) (SVCParamValue -> Either (EncodeErr (Maybe ())) SVCParamValue
toOpaqueSPV SVCParamValue
sb)
where
ocmp :: Either a a -> Either a a -> Ordering
ocmp (Right a
oa) (Right a
ob) = a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
oa a
ob
ocmp (Left a
e) Either a a
_ = [Char] -> Ordering
forall a. HasCallStack => [Char] -> a
error ([Char] -> Ordering) -> [Char] -> Ordering
forall a b. (a -> b) -> a -> b
$ a -> [Char]
forall a. Show a => a -> [Char]
show a
e
ocmp Either a a
_ (Left a
e) = [Char] -> Ordering
forall a. HasCallStack => [Char] -> a
error ([Char] -> Ordering) -> [Char] -> Ordering
forall a b. (a -> b) -> a -> b
$ a -> [Char]
forall a. Show a => a -> [Char]
show a
e
instance Show SVCParamValue where
showsPrec :: Int -> SVCParamValue -> ShowS
showsPrec Int
p (SVCParamValue a
a) =
Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
app_prec) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
[Char] -> ShowS
showString [Char]
"SVCParamValue "
ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec (Int
app_prec Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) a
a
where
app_prec :: Int
app_prec = Int
10
instance Presentable SVCParamValue where
present :: SVCParamValue -> Builder -> Builder
present (SVCParamValue a
a) = a -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present a
a
data OpaqueSPV n where
OpaqueSPV :: Nat16 n => SB.ShortByteString -> OpaqueSPV n
deriving instance Eq (OpaqueSPV n)
deriving instance Ord (OpaqueSPV n)
deriving instance Show (OpaqueSPV n)
instance Nat16 n => KnownSVCParamValue (OpaqueSPV n) where
spvKey :: forall b -> (b ~ OpaqueSPV n) => SVCParamKey
spvKey _ = Word16 -> SVCParamKey
SVCParamKey (Word16 -> SVCParamKey) -> Word16 -> SVCParamKey
forall a b. (a -> b) -> a -> b
$ natToWord16 n
encodeSPV :: forall r s. ErrorContext r => OpaqueSPV n -> SPut s r
encodeSPV (OpaqueSPV ShortByteString
txt) = ShortByteString -> SPut s r
forall r s. ErrorContext r => ShortByteString -> SPut s r
putShortByteString ShortByteString
txt
decodeSPV :: forall b -> (b ~ OpaqueSPV n) => Int -> SGet SVCParamValue
decodeSPV _ = OpaqueSPV n -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue (OpaqueSPV n -> SVCParamValue)
-> (ShortByteString -> OpaqueSPV n)
-> ShortByteString
-> SVCParamValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (n :: Nat). Nat16 n => ShortByteString -> OpaqueSPV n
OpaqueSPV @n (ShortByteString -> SVCParamValue)
-> (Int -> SGet ShortByteString) -> Int -> SGet SVCParamValue
forall (m :: * -> *) b c a.
Functor m =>
(b -> c) -> (a -> m b) -> a -> m c
<.> Int -> SGet ShortByteString
getShortNByteString
instance Nat16 n => Presentable (OpaqueSPV n) where
present :: OpaqueSPV n -> Builder -> Builder
present (OpaqueSPV ShortByteString
v) =
[Char] -> Builder -> Builder
forall a. Presentable a => a -> Builder -> Builder
present [Char]
"key" (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 (natToWord16 n)
(Builder -> Builder) -> (Builder -> Builder) -> Builder -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Builder -> Builder)
-> (Builder -> Builder) -> Bool -> Builder -> Builder
forall a. a -> a -> Bool -> a
bool Builder -> Builder
forall a. a -> a
id (forall a. Presentable a => Char -> a -> Builder -> Builder
presentCharSep @DnsText Char
'=' (ShortByteString -> DnsText
forall a b. Coercible a b => a -> b
coerce ShortByteString
v)) ((ShortByteString -> Int
SB.length ShortByteString
v) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0)
opaqueSPV :: Word16 -> SB.ShortByteString -> SVCParamValue
opaqueSPV :: Word16 -> ShortByteString -> SVCParamValue
opaqueSPV Word16
w ShortByteString
bs = Word16
-> (forall (n :: Nat) -> Nat16 n => SVCParamValue) -> SVCParamValue
forall r. Word16 -> (forall (n :: Nat) -> Nat16 n => r) -> r
withNat16 Word16
w forall (n :: Nat) -> Nat16 n => SVCParamValue
go
where
go :: forall (n :: Nat) -> Nat16 n => SVCParamValue
go :: forall (n :: Nat) -> Nat16 n => SVCParamValue
go n = OpaqueSPV n -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue (OpaqueSPV n -> SVCParamValue) -> OpaqueSPV n -> SVCParamValue
forall a b. (a -> b) -> a -> b
$ (ShortByteString -> OpaqueSPV n
forall (n :: Nat). Nat16 n => ShortByteString -> OpaqueSPV n
OpaqueSPV ShortByteString
bs :: OpaqueSPV n)
toOpaqueSPV :: SVCParamValue -> Either (EncodeErr (Maybe ())) SVCParamValue
toOpaqueSPV :: SVCParamValue -> Either (EncodeErr (Maybe ())) SVCParamValue
toOpaqueSPV s :: SVCParamValue
s@(SVCParamValue -> SVCParamKey
svcParamValueKey -> SVCParamKey
k) = Word16
-> (forall (n :: Nat) ->
Nat16 n => Either (EncodeErr (Maybe ())) SVCParamValue)
-> Either (EncodeErr (Maybe ())) SVCParamValue
forall r. Word16 -> (forall (n :: Nat) -> Nat16 n => r) -> r
withNat16 (SVCParamKey -> Word16
forall a b. Coercible a b => a -> b
coerce SVCParamKey
k) forall (n :: Nat) ->
Nat16 n => Either (EncodeErr (Maybe ())) SVCParamValue
go
where
go :: forall (n :: Nat) -> Nat16 n
=> Either (EncodeErr (Maybe ())) SVCParamValue
go :: forall (n :: Nat) ->
Nat16 n => Either (EncodeErr (Maybe ())) SVCParamValue
go n | SVCParamKey -> SVCParamValue -> Bool
isOpaque SVCParamKey
k SVCParamValue
s = SVCParamValue -> Either (EncodeErr (Maybe ())) SVCParamValue
forall a b. b -> Either a b
Right SVCParamValue
s
| Bool
otherwise
= OpaqueSPV n -> SVCParamValue
forall a. KnownSVCParamValue a => a -> SVCParamValue
SVCParamValue (OpaqueSPV n -> SVCParamValue)
-> (ByteString -> OpaqueSPV n) -> ByteString -> SVCParamValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> OpaqueSPV n
mkopaque (ByteString -> SVCParamValue)
-> Either (EncodeErr (Maybe ())) ByteString
-> Either (EncodeErr (Maybe ())) SVCParamValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall s. SPut s ()) -> Either (EncodeErr (Maybe ())) ByteString
forall r.
ErrorContext r =>
(forall s. SPut s r) -> Either (EncodeErr (Maybe r)) ByteString
encodeVerbatim do SVCParamValue -> SPut s ()
forall r s. ErrorContext r => SVCParamValue -> SPut s r
spvEncode SVCParamValue
s
where
mkopaque :: ByteString -> OpaqueSPV n
mkopaque :: ByteString -> OpaqueSPV n
mkopaque ByteString
bs = ShortByteString -> OpaqueSPV n
forall (n :: Nat). Nat16 n => ShortByteString -> OpaqueSPV n
OpaqueSPV (ShortByteString -> OpaqueSPV n) -> ShortByteString -> OpaqueSPV n
forall a b. (a -> b) -> a -> b
$ ByteString -> ShortByteString
SB.toShort ByteString
bs
isOpaque :: SVCParamKey -> SVCParamValue -> Bool
isOpaque :: SVCParamKey -> SVCParamValue -> Bool
isOpaque SVCParamKey
k SVCParamValue
spv = Word16 -> (forall (n :: Nat) -> Nat16 n => Bool) -> Bool
forall r. Word16 -> (forall (n :: Nat) -> Nat16 n => r) -> r
withNat16 (SVCParamKey -> Word16
forall a b. Coercible a b => a -> b
coerce SVCParamKey
k) forall (n :: Nat) -> Nat16 n => Bool
go
where
go :: forall (n :: Nat) -> Nat16 n => Bool
go :: forall (n :: Nat) -> Nat16 n => Bool
go n = Maybe (OpaqueSPV n) -> Bool
forall a. Maybe a -> Bool
isJust (SVCParamValue -> Maybe (OpaqueSPV n)
forall a. KnownSVCParamValue a => SVCParamValue -> Maybe a
fromSPV SVCParamValue
spv :: Maybe (OpaqueSPV n))