content: {-# LANGUAGE PatternSynonyms #-}
  {-# LANGUAGE DeriveGeneric #-}
  {-# LANGUAGE ExistentialQuantification #-}
  {-# LANGUAGE StandaloneDeriving #-}
  
  module Hans.Addr (
      Addr(), sameFamily,
      NetworkAddr(..),
      putAddr,
      showAddr,
    ) where
  
  import           Hans.Addr.Types
  import qualified Hans.IP4.Packet as IP4
  
  import Data.Hashable (Hashable)
  import Data.Typeable (Typeable)
  import GHC.Generics (Generic)
  
  
  class (Hashable addr, Show addr, Typeable addr, Eq addr, Generic addr)
    => NetworkAddr addr where
    -- | Forget what kind of address this is.
    toAddr :: addr -> Addr
  
    -- | Try to remember what this opaque address was.
    fromAddr :: Addr -> Maybe addr
  
    -- | Check to see if this address is the wildcard address.
    isWildcardAddr :: addr -> Bool
  
    -- | The wildcard address
    wildcardAddr :: addr -> addr
  
    -- | Check to see if this address is the broadcast address.
    isBroadcastAddr :: addr -> Bool
  
    -- | The broadcast address.
    broadcastAddr :: addr -> addr
  
  
  instance NetworkAddr Addr where
    toAddr                       = id
    fromAddr addr                = Just addr
    isWildcardAddr  (Addr4 addr) = isWildcardAddr addr
    wildcardAddr    (Addr4 addr) = Addr4 (wildcardAddr addr)
    isBroadcastAddr (Addr4 addr) = isBroadcastAddr addr
    broadcastAddr   (Addr4 addr) = Addr4 (broadcastAddr addr)
    {-# INLINE toAddr #-}
    {-# INLINE fromAddr #-}
    {-# INLINE isWildcardAddr #-}
    {-# INLINE wildcardAddr #-}
    {-# INLINE isBroadcastAddr #-}
    {-# INLINE broadcastAddr #-}
  
  
  instance NetworkAddr IP4.IP4 where
    toAddr                           = Addr4
    fromAddr (Addr4 addr)            = Just addr
    isWildcardAddr IP4.WildcardIP4   = True
    isWildcardAddr _                 = False
    wildcardAddr _                   = IP4.WildcardIP4
    isBroadcastAddr IP4.BroadcastIP4 = True
    isBroadcastAddr _                = False
    broadcastAddr _                  = IP4.BroadcastIP4
    {-# INLINE toAddr #-}
    {-# INLINE fromAddr #-}
    {-# INLINE isWildcardAddr #-}
    {-# INLINE wildcardAddr #-}
    {-# INLINE isBroadcastAddr #-}
    {-# INLINE broadcastAddr #-}
  