dnsbase-1.0.0.0: src/Net/DNSBase/RData/A.hs
{-|
Module : Net.DNSBase.RData.A
Description : Address records (A and AAAA)
Copyright : (c) Viktor Dukhovni, 2026
License : BSD-3-Clause
Maintainer : ietf-dane@dukhovni.org
Stability : unstable
The two address RR types parallel the variants of 'Data.IP.IP':
'T_a' wraps the @A@ RR's 'IPv4' payload, 'T_aaaa' wraps the
@AAAA@ RR's 'IPv6' payload. Construct or destructure via the
@T_A@ / @T_AAAA@ pattern constructors. When working with a
polymorphic 'RData' value that may be either, 'evalIP'
dispatches on whichever applies and lifts the address into the
common 'Data.IP.IP' sum.
-}
module Net.DNSBase.RData.A
( T_a(..)
, T_aaaa(..)
, evalIP
) where
import Data.IP (IP(..), IPv4, IPv6)
import Net.DNSBase.Decode.State
import Net.DNSBase.Encode.State
import Net.DNSBase.Present
import Net.DNSBase.RData
import Net.DNSBase.RRTYPE
import Net.DNSBase.Internal.Util (showsP)
-- | The @A@ resource record
-- ([RFC 1035 section 3.4.1](https://tools.ietf.org/html/rfc1035#section-3.4.1))
-- — a 32-bit IPv4 address transmitted as four bytes in network
-- order. The derived 'Ord' is numeric 'IPv4' order, which agrees
-- with canonical RR-content ordering
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
--
-- See 'T_aaaa' for the IPv6-family parallel, and 'evalIP' for a
-- helper that handles either uniformly.
newtype T_a = T_A IPv4 -- ^ 'IPv4' address
deriving (Eq, Ord, Enum)
instance Show T_a where
showsPrec p (T_A a) = showsP p $
showString "T_A \"" . shows a . showChar '"'
instance Presentable T_a where
present (T_A a) = present a
instance KnownRData T_a where
rdType _ = A
{-# INLINE rdType #-}
rdEncode (T_A ip4) = putIPv4 ip4
rdDecode _ _ = const do RData . T_A <$> getIPv4
-- | The @AAAA@ resource record
-- ([RFC 3596 section 2.1](https://tools.ietf.org/html/rfc3596#section-2.1))
-- — a 128-bit IPv6 address transmitted as sixteen bytes in network
-- order. The derived 'Ord' is numeric 'IPv6' order, which agrees
-- with canonical RR-content ordering
-- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).
--
-- See 'T_a' for the IPv4-family parallel, and 'evalIP' for a
-- helper that handles either uniformly.
newtype T_aaaa = T_AAAA IPv6 -- ^ 'IPv6' address
deriving (Eq, Ord)
instance Show T_aaaa where
showsPrec p (T_AAAA a) = showsP p $
showString "T_AAAA \"" . shows a . showChar '"'
instance Presentable T_aaaa where
present (T_AAAA a) = present a
instance KnownRData T_aaaa where
rdType _ = AAAA
{-# INLINE rdType #-}
rdEncode (T_AAAA ip6) = putIPv6 ip6
rdDecode _ _ = const do RData . T_AAAA <$> getIPv6
-- | Apply the supplied function to whichever IP address an 'RData'
-- carries, lifting the 'T_a' or 'T_aaaa' payload into the unified
-- 'Data.IP.IP' sum. Returns 'Nothing' for 'RData' of any other type.
--
-- > evalIP id (RData (T_A ip)) == Just (IPv4 ip)
-- > evalIP id (RData (T_AAAA ip)) == Just (IPv6 ip)
evalIP :: (IP -> a) -> RData -> Maybe a
evalIP f (fromRData -> Just (T_A ip)) = Just $! f (IPv4 ip)
evalIP f (fromRData -> Just (T_AAAA ip)) = Just $! f (IPv6 ip)
evalIP _ _ = Nothing