    -- |
    -- Module      : Data.PostgreSQL.NetworkAddress
    -- Copyright   : 2015-2018 Kei Hibino
    -- License     : BSD3
    --
    -- Maintainer  : ex8k.hibino@gmail.com
    -- Stability   : experimental
    -- Portability : unknown
    --
    -- This module defines network-address types of PostgreSQL.
    -- http://www.postgresql.org/docs/current/static/datatype-net-types.html
    module Data.PostgreSQL.NetworkAddress
           ( -- * Definitions about inet and cidr types
             Inet (..), Cidr (..), cidr4, cidr4', cidr6, cidr6',

             -- * Definitions about the address type which is the pair of host-address and mask
             NetAddress (..), netAddress4, netAddress6,

             -- * Definitions about the host-address types
             V4HostAddress (..), v4HostAddressOctets,
             V6HostAddress (..), v6HostAddressLong, v6HostAddressWords,
             v6HostAddress, v6HostAddressL, v6HostAddressR,
           ) where

    import Control.Applicative (pure)
    import Control.Monad (guard)
    import Data.Word (Word8, Word16, Word32)
    import Data.Bits (shiftL, shiftR, (.&.), (.|.))

    -- | Host address type along with IPv4 address bytes with IPv4 string order.
    data V4HostAddress =
      V4HostAddress !Word8 !Word8 !Word8 !Word8
      deriving (V4HostAddress -> V4HostAddress -> Bool
    (V4HostAddress -> V4HostAddress -> Bool)
    -> (V4HostAddress -> V4HostAddress -> Bool) -> Eq V4HostAddress
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: V4HostAddress -> V4HostAddress -> Bool
    == :: V4HostAddress -> V4HostAddress -> Bool
    $c/= :: V4HostAddress -> V4HostAddress -> Bool
    /= :: V4HostAddress -> V4HostAddress -> Bool
    Eq, Eq V4HostAddress
    Eq V4HostAddress =>
    (V4HostAddress -> V4HostAddress -> Ordering)
    -> (V4HostAddress -> V4HostAddress -> Bool)
    -> (V4HostAddress -> V4HostAddress -> Bool)
    -> (V4HostAddress -> V4HostAddress -> Bool)
    -> (V4HostAddress -> V4HostAddress -> Bool)
    -> (V4HostAddress -> V4HostAddress -> V4HostAddress)
    -> (V4HostAddress -> V4HostAddress -> V4HostAddress)
    -> Ord V4HostAddress
    V4HostAddress -> V4HostAddress -> Bool
    V4HostAddress -> V4HostAddress -> Ordering
    V4HostAddress -> V4HostAddress -> V4HostAddress
    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 :: V4HostAddress -> V4HostAddress -> Ordering
    compare :: V4HostAddress -> V4HostAddress -> Ordering
    $c< :: V4HostAddress -> V4HostAddress -> Bool
    < :: V4HostAddress -> V4HostAddress -> Bool
    $c<= :: V4HostAddress -> V4HostAddress -> Bool
    <= :: V4HostAddress -> V4HostAddress -> Bool
    $c> :: V4HostAddress -> V4HostAddress -> Bool
    > :: V4HostAddress -> V4HostAddress -> Bool
    $c>= :: V4HostAddress -> V4HostAddress -> Bool
    >= :: V4HostAddress -> V4HostAddress -> Bool
    $cmax :: V4HostAddress -> V4HostAddress -> V4HostAddress
    max :: V4HostAddress -> V4HostAddress -> V4HostAddress
    $cmin :: V4HostAddress -> V4HostAddress -> V4HostAddress
    min :: V4HostAddress -> V4HostAddress -> V4HostAddress
    Ord, Int -> V4HostAddress -> ShowS
    [V4HostAddress] -> ShowS
    V4HostAddress -> String
    (Int -> V4HostAddress -> ShowS)
    -> (V4HostAddress -> String)
    -> ([V4HostAddress] -> ShowS)
    -> Show V4HostAddress
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> V4HostAddress -> ShowS
    showsPrec :: Int -> V4HostAddress -> ShowS
    $cshow :: V4HostAddress -> String
    show :: V4HostAddress -> String
    $cshowList :: [V4HostAddress] -> ShowS
    showList :: [V4HostAddress] -> ShowS
    Show, ReadPrec [V4HostAddress]
    ReadPrec V4HostAddress
    Int -> ReadS V4HostAddress
    ReadS [V4HostAddress]
    (Int -> ReadS V4HostAddress)
    -> ReadS [V4HostAddress]
    -> ReadPrec V4HostAddress
    -> ReadPrec [V4HostAddress]
    -> Read V4HostAddress
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS V4HostAddress
    readsPrec :: Int -> ReadS V4HostAddress
    $creadList :: ReadS [V4HostAddress]
    readList :: ReadS [V4HostAddress]
    $creadPrec :: ReadPrec V4HostAddress
    readPrec :: ReadPrec V4HostAddress
    $creadListPrec :: ReadPrec [V4HostAddress]
    readListPrec :: ReadPrec [V4HostAddress]
    Read)

    v4HostAddressOctets :: V4HostAddress -> (Word8, Word8, Word8, Word8)
    v4HostAddressOctets :: V4HostAddress -> (Word8, Word8, Word8, Word8)
    v4HostAddressOctets (V4HostAddress Word8
    a Word8
    b Word8
    c Word8
    d) = (Word8
    a, Word8
    b, Word8
    c, Word8
    d)

    -- | Host address type along with IPv6 address words with IPv6 string order.
    --   Each 'Word16' value is host byte order.
    --   Host byte order is portable in programs on its own host.
    --   Network byte order is only needed, when communicating other hosts.
    data V6HostAddress =
      V6HostAddress !Word16 !Word16 !Word16 !Word16 !Word16 !Word16 !Word16 !Word16
      deriving (V6HostAddress -> V6HostAddress -> Bool
    (V6HostAddress -> V6HostAddress -> Bool)
    -> (V6HostAddress -> V6HostAddress -> Bool) -> Eq V6HostAddress
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: V6HostAddress -> V6HostAddress -> Bool
    == :: V6HostAddress -> V6HostAddress -> Bool
    $c/= :: V6HostAddress -> V6HostAddress -> Bool
    /= :: V6HostAddress -> V6HostAddress -> Bool
    Eq, Eq V6HostAddress
    Eq V6HostAddress =>
    (V6HostAddress -> V6HostAddress -> Ordering)
    -> (V6HostAddress -> V6HostAddress -> Bool)
    -> (V6HostAddress -> V6HostAddress -> Bool)
    -> (V6HostAddress -> V6HostAddress -> Bool)
    -> (V6HostAddress -> V6HostAddress -> Bool)
    -> (V6HostAddress -> V6HostAddress -> V6HostAddress)
    -> (V6HostAddress -> V6HostAddress -> V6HostAddress)
    -> Ord V6HostAddress
    V6HostAddress -> V6HostAddress -> Bool
    V6HostAddress -> V6HostAddress -> Ordering
    V6HostAddress -> V6HostAddress -> V6HostAddress
    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 :: V6HostAddress -> V6HostAddress -> Ordering
    compare :: V6HostAddress -> V6HostAddress -> Ordering
    $c< :: V6HostAddress -> V6HostAddress -> Bool
    < :: V6HostAddress -> V6HostAddress -> Bool
    $c<= :: V6HostAddress -> V6HostAddress -> Bool
    <= :: V6HostAddress -> V6HostAddress -> Bool
    $c> :: V6HostAddress -> V6HostAddress -> Bool
    > :: V6HostAddress -> V6HostAddress -> Bool
    $c>= :: V6HostAddress -> V6HostAddress -> Bool
    >= :: V6HostAddress -> V6HostAddress -> Bool
    $cmax :: V6HostAddress -> V6HostAddress -> V6HostAddress
    max :: V6HostAddress -> V6HostAddress -> V6HostAddress
    $cmin :: V6HostAddress -> V6HostAddress -> V6HostAddress
    min :: V6HostAddress -> V6HostAddress -> V6HostAddress
    Ord, Int -> V6HostAddress -> ShowS
    [V6HostAddress] -> ShowS
    V6HostAddress -> String
    (Int -> V6HostAddress -> ShowS)
    -> (V6HostAddress -> String)
    -> ([V6HostAddress] -> ShowS)
    -> Show V6HostAddress
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> V6HostAddress -> ShowS
    showsPrec :: Int -> V6HostAddress -> ShowS
    $cshow :: V6HostAddress -> String
    show :: V6HostAddress -> String
    $cshowList :: [V6HostAddress] -> ShowS
    showList :: [V6HostAddress] -> ShowS
    Show, ReadPrec [V6HostAddress]
    ReadPrec V6HostAddress
    Int -> ReadS V6HostAddress
    ReadS [V6HostAddress]
    (Int -> ReadS V6HostAddress)
    -> ReadS [V6HostAddress]
    -> ReadPrec V6HostAddress
    -> ReadPrec [V6HostAddress]
    -> Read V6HostAddress
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS V6HostAddress
    readsPrec :: Int -> ReadS V6HostAddress
    $creadList :: ReadS [V6HostAddress]
    readList :: ReadS [V6HostAddress]
    $creadPrec :: ReadPrec V6HostAddress
    readPrec :: ReadPrec V6HostAddress
    $creadListPrec :: ReadPrec [V6HostAddress]
    readListPrec :: ReadPrec [V6HostAddress]
    Read)

    v6HostAddressLong :: Word16 -> Word16 -> Word16 -> Word16
                      -> Word16 -> Word16 -> Word16 -> Word16
                      -> V6HostAddress
    v6HostAddressLong :: Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> V6HostAddress
    v6HostAddressLong = Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> V6HostAddress
    V6HostAddress

    v6HostAddress :: [Word16] -> [Word16] -> Maybe V6HostAddress
    v6HostAddress :: [Word16] -> [Word16] -> Maybe V6HostAddress
    v6HostAddress [Word16]
    ls [Word16]
    rs  = do
      let zlength :: Int
    zlength = Int
    8 {- v6 length -} Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - [Word16] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length ([Word16]
    ls [Word16] -> [Word16] -> [Word16]
    forall a. [a] -> [a] -> [a]
    ++ [Word16]
    rs)
      Bool -> Maybe ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard (Bool -> Maybe ()) -> Bool -> Maybe ()
    forall a b. (a -> b) -> a -> b
    $ Int
    zlength Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    0
      [a, b, c, d, e, f, g, h]  <-  [Word16] -> Maybe [Word16]
    forall a. a -> Maybe a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([Word16] -> Maybe [Word16]) -> [Word16] -> Maybe [Word16]
    forall a b. (a -> b) -> a -> b
    $ [Word16]
    ls [Word16] -> [Word16] -> [Word16]
    forall a. [a] -> [a] -> [a]
    ++ Int -> Word16 -> [Word16]
    forall a. Int -> a -> [a]
    replicate Int
    zlength Word16
    0 [Word16] -> [Word16] -> [Word16]
    forall a. [a] -> [a] -> [a]
    ++ [Word16]
    rs
      pure $ v6HostAddressLong a b c d e f g h

    v6HostAddressR :: [Word16] -> Maybe V6HostAddress
    v6HostAddressR :: [Word16] -> Maybe V6HostAddress
    v6HostAddressR = [Word16] -> [Word16] -> Maybe V6HostAddress
    v6HostAddress []

    v6HostAddressL :: [Word16] -> Maybe V6HostAddress
    v6HostAddressL :: [Word16] -> Maybe V6HostAddress
    v6HostAddressL [Word16]
    ls = [Word16] -> [Word16] -> Maybe V6HostAddress
    v6HostAddress [Word16]
    ls []

    v6HostAddressWords :: V6HostAddress -> (Word16, Word16, Word16, Word16, Word16, Word16, Word16, Word16)
    v6HostAddressWords :: V6HostAddress
    -> (Word16, Word16, Word16, Word16, Word16, Word16, Word16, Word16)
    v6HostAddressWords (V6HostAddress Word16
    a Word16
    b Word16
    c Word16
    d Word16
    e Word16
    f Word16
    g Word16
    h) =
      (Word16
    a, Word16
    b, Word16
    c, Word16
    d, Word16
    e, Word16
    f, Word16
    g, Word16
    h)

    -- | IPv4 or IPv6 netword address corresponding <host-addr>/<mask>.
    --   eg. '192.168.0.1/24'
    data NetAddress
      = NetAddress4 !V4HostAddress !Word8
      | NetAddress6 !V6HostAddress !Word8
      deriving (NetAddress -> NetAddress -> Bool
    (NetAddress -> NetAddress -> Bool)
    -> (NetAddress -> NetAddress -> Bool) -> Eq NetAddress
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: NetAddress -> NetAddress -> Bool
    == :: NetAddress -> NetAddress -> Bool
    $c/= :: NetAddress -> NetAddress -> Bool
    /= :: NetAddress -> NetAddress -> Bool
    Eq, Eq NetAddress
    Eq NetAddress =>
    (NetAddress -> NetAddress -> Ordering)
    -> (NetAddress -> NetAddress -> Bool)
    -> (NetAddress -> NetAddress -> Bool)
    -> (NetAddress -> NetAddress -> Bool)
    -> (NetAddress -> NetAddress -> Bool)
    -> (NetAddress -> NetAddress -> NetAddress)
    -> (NetAddress -> NetAddress -> NetAddress)
    -> Ord NetAddress
    NetAddress -> NetAddress -> Bool
    NetAddress -> NetAddress -> Ordering
    NetAddress -> NetAddress -> NetAddress
    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 :: NetAddress -> NetAddress -> Ordering
    compare :: NetAddress -> NetAddress -> Ordering
    $c< :: NetAddress -> NetAddress -> Bool
    < :: NetAddress -> NetAddress -> Bool
    $c<= :: NetAddress -> NetAddress -> Bool
    <= :: NetAddress -> NetAddress -> Bool
    $c> :: NetAddress -> NetAddress -> Bool
    > :: NetAddress -> NetAddress -> Bool
    $c>= :: NetAddress -> NetAddress -> Bool
    >= :: NetAddress -> NetAddress -> Bool
    $cmax :: NetAddress -> NetAddress -> NetAddress
    max :: NetAddress -> NetAddress -> NetAddress
    $cmin :: NetAddress -> NetAddress -> NetAddress
    min :: NetAddress -> NetAddress -> NetAddress
    Ord, Int -> NetAddress -> ShowS
    [NetAddress] -> ShowS
    NetAddress -> String
    (Int -> NetAddress -> ShowS)
    -> (NetAddress -> String)
    -> ([NetAddress] -> ShowS)
    -> Show NetAddress
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> NetAddress -> ShowS
    showsPrec :: Int -> NetAddress -> ShowS
    $cshow :: NetAddress -> String
    show :: NetAddress -> String
    $cshowList :: [NetAddress] -> ShowS
    showList :: [NetAddress] -> ShowS
    Show, ReadPrec [NetAddress]
    ReadPrec NetAddress
    Int -> ReadS NetAddress
    ReadS [NetAddress]
    (Int -> ReadS NetAddress)
    -> ReadS [NetAddress]
    -> ReadPrec NetAddress
    -> ReadPrec [NetAddress]
    -> Read NetAddress
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS NetAddress
    readsPrec :: Int -> ReadS NetAddress
    $creadList :: ReadS [NetAddress]
    readList :: ReadS [NetAddress]
    $creadPrec :: ReadPrec NetAddress
    readPrec :: ReadPrec NetAddress
    $creadListPrec :: ReadPrec [NetAddress]
    readListPrec :: ReadPrec [NetAddress]
    Read)

    vmask4 :: (Ord a, Integral a) => a -> Bool
    vmask4 :: forall a. (Ord a, Integral a) => a -> Bool
    vmask4 = (a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    32)

    -- | Make IPv4 NetAddress type consistent with IPv4 mask
    netAddress4 :: V4HostAddress     -- ^ IPv4 host-address
                -> Word8             -- ^ IPv4 mask 0-32
                -> Maybe NetAddress  -- ^ result NetAddress
    netAddress4 :: V4HostAddress -> Word8 -> Maybe NetAddress
    netAddress4 V4HostAddress
    a4 Word8
    m
      | Word8 -> Bool
    forall a. (Ord a, Integral a) => a -> Bool
    vmask4 Word8
    m   =  NetAddress -> Maybe NetAddress
    forall a. a -> Maybe a
    Just (NetAddress -> Maybe NetAddress) -> NetAddress -> Maybe NetAddress
    forall a b. (a -> b) -> a -> b
    $ V4HostAddress -> Word8 -> NetAddress
    NetAddress4 V4HostAddress
    a4 Word8
    m
      | Bool
    otherwise  =  Maybe NetAddress
    forall a. Maybe a
    Nothing

    vmask6 :: (Ord a, Integral a) => a -> Bool
    vmask6 :: forall a. (Ord a, Integral a) => a -> Bool
    vmask6 = (a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    128)

    -- | Make IPv6 NetAddress type consistent with IPv6 mask
    netAddress6 :: V6HostAddress     -- ^ IPv6 host-address
                -> Word8             -- ^ IPv6 mask 0-128
                -> Maybe NetAddress  -- ^ result NetAddress
    netAddress6 :: V6HostAddress -> Word8 -> Maybe NetAddress
    netAddress6 V6HostAddress
    a6 Word8
    m
      | Word8 -> Bool
    forall a. (Ord a, Integral a) => a -> Bool
    vmask6 Word8
    m   =  NetAddress -> Maybe NetAddress
    forall a. a -> Maybe a
    Just (NetAddress -> Maybe NetAddress) -> NetAddress -> Maybe NetAddress
    forall a b. (a -> b) -> a -> b
    $ V6HostAddress -> Word8 -> NetAddress
    NetAddress6 V6HostAddress
    a6 Word8
    m
      | Bool
    otherwise  =  Maybe NetAddress
    forall a. Maybe a
    Nothing

    -- | Corresponding to INET type of PostgreSQL
    newtype Inet = Inet NetAddress  deriving (Inet -> Inet -> Bool
    (Inet -> Inet -> Bool) -> (Inet -> Inet -> Bool) -> Eq Inet
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Inet -> Inet -> Bool
    == :: Inet -> Inet -> Bool
    $c/= :: Inet -> Inet -> Bool
    /= :: Inet -> Inet -> Bool
    Eq, Eq Inet
    Eq Inet =>
    (Inet -> Inet -> Ordering)
    -> (Inet -> Inet -> Bool)
    -> (Inet -> Inet -> Bool)
    -> (Inet -> Inet -> Bool)
    -> (Inet -> Inet -> Bool)
    -> (Inet -> Inet -> Inet)
    -> (Inet -> Inet -> Inet)
    -> Ord Inet
    Inet -> Inet -> Bool
    Inet -> Inet -> Ordering
    Inet -> Inet -> Inet
    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 :: Inet -> Inet -> Ordering
    compare :: Inet -> Inet -> Ordering
    $c< :: Inet -> Inet -> Bool
    < :: Inet -> Inet -> Bool
    $c<= :: Inet -> Inet -> Bool
    <= :: Inet -> Inet -> Bool
    $c> :: Inet -> Inet -> Bool
    > :: Inet -> Inet -> Bool
    $c>= :: Inet -> Inet -> Bool
    >= :: Inet -> Inet -> Bool
    $cmax :: Inet -> Inet -> Inet
    max :: Inet -> Inet -> Inet
    $cmin :: Inet -> Inet -> Inet
    min :: Inet -> Inet -> Inet
    Ord, Int -> Inet -> ShowS
    [Inet] -> ShowS
    Inet -> String
    (Int -> Inet -> ShowS)
    -> (Inet -> String) -> ([Inet] -> ShowS) -> Show Inet
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Inet -> ShowS
    showsPrec :: Int -> Inet -> ShowS
    $cshow :: Inet -> String
    show :: Inet -> String
    $cshowList :: [Inet] -> ShowS
    showList :: [Inet] -> ShowS
    Show, ReadPrec [Inet]
    ReadPrec Inet
    Int -> ReadS Inet
    ReadS [Inet]
    (Int -> ReadS Inet)
    -> ReadS [Inet] -> ReadPrec Inet -> ReadPrec [Inet] -> Read Inet
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Inet
    readsPrec :: Int -> ReadS Inet
    $creadList :: ReadS [Inet]
    readList :: ReadS [Inet]
    $creadPrec :: ReadPrec Inet
    readPrec :: ReadPrec Inet
    $creadListPrec :: ReadPrec [Inet]
    readListPrec :: ReadPrec [Inet]
    Read)

    -- | Corresponding to CIDR type of PostgreSQL
    newtype Cidr = Cidr NetAddress  deriving (Cidr -> Cidr -> Bool
    (Cidr -> Cidr -> Bool) -> (Cidr -> Cidr -> Bool) -> Eq Cidr
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Cidr -> Cidr -> Bool
    == :: Cidr -> Cidr -> Bool
    $c/= :: Cidr -> Cidr -> Bool
    /= :: Cidr -> Cidr -> Bool
    Eq, Eq Cidr
    Eq Cidr =>
    (Cidr -> Cidr -> Ordering)
    -> (Cidr -> Cidr -> Bool)
    -> (Cidr -> Cidr -> Bool)
    -> (Cidr -> Cidr -> Bool)
    -> (Cidr -> Cidr -> Bool)
    -> (Cidr -> Cidr -> Cidr)
    -> (Cidr -> Cidr -> Cidr)
    -> Ord Cidr
    Cidr -> Cidr -> Bool
    Cidr -> Cidr -> Ordering
    Cidr -> Cidr -> Cidr
    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 :: Cidr -> Cidr -> Ordering
    compare :: Cidr -> Cidr -> Ordering
    $c< :: Cidr -> Cidr -> Bool
    < :: Cidr -> Cidr -> Bool
    $c<= :: Cidr -> Cidr -> Bool
    <= :: Cidr -> Cidr -> Bool
    $c> :: Cidr -> Cidr -> Bool
    > :: Cidr -> Cidr -> Bool
    $c>= :: Cidr -> Cidr -> Bool
    >= :: Cidr -> Cidr -> Bool
    $cmax :: Cidr -> Cidr -> Cidr
    max :: Cidr -> Cidr -> Cidr
    $cmin :: Cidr -> Cidr -> Cidr
    min :: Cidr -> Cidr -> Cidr
    Ord, Int -> Cidr -> ShowS
    [Cidr] -> ShowS
    Cidr -> String
    (Int -> Cidr -> ShowS)
    -> (Cidr -> String) -> ([Cidr] -> ShowS) -> Show Cidr
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Cidr -> ShowS
    showsPrec :: Int -> Cidr -> ShowS
    $cshow :: Cidr -> String
    show :: Cidr -> String
    $cshowList :: [Cidr] -> ShowS
    showList :: [Cidr] -> ShowS
    Show, ReadPrec [Cidr]
    ReadPrec Cidr
    Int -> ReadS Cidr
    ReadS [Cidr]
    (Int -> ReadS Cidr)
    -> ReadS [Cidr] -> ReadPrec Cidr -> ReadPrec [Cidr] -> Read Cidr
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Cidr
    readsPrec :: Int -> ReadS Cidr
    $creadList :: ReadS [Cidr]
    readList :: ReadS [Cidr]
    $creadPrec :: ReadPrec Cidr
    readPrec :: ReadPrec Cidr
    $creadListPrec :: ReadPrec [Cidr]
    readListPrec :: ReadPrec [Cidr]
    Read)

    maskCidr4 :: V4HostAddress -> Word8 -> (Word32, Word32)
    maskCidr4 :: V4HostAddress -> Word8 -> (Word32, Word32)
    maskCidr4 (V4HostAddress Word8
    w0 Word8
    w1 Word8
    w2 Word8
    w3) Word8
    m =
        (Word32
    a4 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. (Word32
    1 Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    mi Word32 -> Word32 -> Word32
    forall a. Num a => a -> a -> a
    - Word32
    1) Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftL` (Int
    32 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    mi), Word32
    a4)
      where
        mi :: Int
    mi = Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    m
        a4 :: Word32
        a4 :: Word32
    a4 = (Word32 -> Word32 -> Word32) -> Word32 -> [Word32] -> Word32
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    (.|.) Word32
    0 ([Word32] -> Word32) -> [Word32] -> Word32
    forall a b. (a -> b) -> a -> b
    $ (Word8 -> Int -> Word32) -> [Word8] -> [Int] -> [Word32]
    forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
    zipWith
             (\Word8
    w Int
    x -> Word8 -> Word32
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    w Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    x)
             [Word8
    w3, Word8
    w2, Word8
    w1, Word8
    w0]
             [Int
    0,Int
    8 ..]

    -- | Same as cidr4 except for dropping host-address bits along with mask
    cidr4' :: V4HostAddress -> Word8 -> Maybe Cidr
    cidr4' :: V4HostAddress -> Word8 -> Maybe Cidr
    cidr4' V4HostAddress
    ha0 Word8
    m = do
        Bool -> Maybe ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard (Bool -> Maybe ()) -> Bool -> Maybe ()
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Bool
    forall a. (Ord a, Integral a) => a -> Bool
    vmask4 Word8
    m
        let (Word32
    ra, Word32
    _) = V4HostAddress -> Word8 -> (Word32, Word32)
    maskCidr4 V4HostAddress
    ha0 Word8
    m
            ha :: V4HostAddress
    ha = [Word8] -> V4HostAddress
    fromList4 ([Word8] -> V4HostAddress) -> [Word8] -> V4HostAddress
    forall a b. (a -> b) -> a -> b
    $ (Int -> Word8) -> [Int] -> [Word8]
    forall a b. (a -> b) -> [a] -> [b]
    map (Word32 -> Word8
    byte (Word32 -> Word8) -> (Int -> Word32) -> Int -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Word32
    ra Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftR`)) [Int
    24,Int
    16,Int
    8,Int
    0]
        Cidr -> Maybe Cidr
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Cidr -> Maybe Cidr)
    -> (NetAddress -> Cidr) -> NetAddress -> Maybe Cidr
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . NetAddress -> Cidr
    Cidr (NetAddress -> Maybe Cidr) -> NetAddress -> Maybe Cidr
    forall a b. (a -> b) -> a -> b
    $ V4HostAddress -> Word8 -> NetAddress
    NetAddress4 V4HostAddress
    ha Word8
    m
      where
        byte :: Word32 -> Word8
    byte = Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> (Word32 -> Word32) -> Word32 -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. Word32
    0xff)
        fromList4 :: [Word8] -> V4HostAddress
    fromList4 [Word8]
    ws = Word8 -> Word8 -> Word8 -> Word8 -> V4HostAddress
    V4HostAddress Word8
    w0 Word8
    w1 Word8
    w2 Word8
    w3
          where [Word8
    w0, Word8
    w1, Word8
    w2, Word8
    w3] = [Word8]
    ws

    -- | Make Cidr type of IPv4 from host-address bits consistent with mask
    cidr4 :: V4HostAddress -> Word8 -> Maybe Cidr
    cidr4 :: V4HostAddress -> Word8 -> Maybe Cidr
    cidr4 V4HostAddress
    ha Word8
    m = do
      na <- V4HostAddress -> Word8 -> Maybe NetAddress
    netAddress4 V4HostAddress
    ha Word8
    m
      let (ma, ra) = maskCidr4 ha m
      guard $ ma == ra
      return $ Cidr na

    maskCidr6 :: V6HostAddress -> Word8 -> (Integer, Integer)
    maskCidr6 :: V6HostAddress -> Word8 -> (Integer, Integer)
    maskCidr6 (V6HostAddress Word16
    w0 Word16
    w1 Word16
    w2 Word16
    w3 Word16
    w4 Word16
    w5 Word16
    w6 Word16
    w7) Word8
    m =
        (Integer
    a6 Integer -> Integer -> Integer
    forall a. Bits a => a -> a -> a
    .&. (Integer
    1 Integer -> Int -> Integer
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    mi Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    1) Integer -> Int -> Integer
    forall a. Bits a => a -> Int -> a
    `shiftL` (Int
    128 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    mi), Integer
    a6)
      where
        mi :: Int
    mi = Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    m
        a6 :: Integer
        a6 :: Integer
    a6 = (Integer -> Integer -> Integer) -> Integer -> [Integer] -> Integer
    forall a b. (a -> b -> b) -> b -> [a] -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr Integer -> Integer -> Integer
    forall a. Bits a => a -> a -> a
    (.|.) Integer
    0 ([Integer] -> Integer) -> [Integer] -> Integer
    forall a b. (a -> b) -> a -> b
    $ (Word16 -> Int -> Integer) -> [Word16] -> [Int] -> [Integer]
    forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
    zipWith
             (\Word16
    w Int
    x -> Word16 -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word16
    w Integer -> Int -> Integer
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    x)
             [Word16
    w7, Word16
    w6, Word16
    w5, Word16
    w4, Word16
    w3, Word16
    w2, Word16
    w1, Word16
    w0]
             [Int
    0,Int
    16 ..]

    -- | Same as cidr6 except for dropping host-address bits along with mask
    cidr6' :: V6HostAddress -> Word8 -> Maybe Cidr
    cidr6' :: V6HostAddress -> Word8 -> Maybe Cidr
    cidr6' V6HostAddress
    ha0 Word8
    m = do
        Bool -> Maybe ()
    forall (f :: * -> *). Alternative f => Bool -> f ()
    guard (Bool -> Maybe ()) -> Bool -> Maybe ()
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Bool
    forall a. (Ord a, Integral a) => a -> Bool
    vmask6 Word8
    m
        let (Integer
    ra, Integer
    _) = V6HostAddress -> Word8 -> (Integer, Integer)
    maskCidr6 V6HostAddress
    ha0 Word8
    m
            ha :: V6HostAddress
    ha = [Word16] -> V6HostAddress
    fromList6 ([Word16] -> V6HostAddress) -> [Word16] -> V6HostAddress
    forall a b. (a -> b) -> a -> b
    $ (Int -> Word16) -> [Int] -> [Word16]
    forall a b. (a -> b) -> [a] -> [b]
    map (Integer -> Word16
    word (Integer -> Word16) -> (Int -> Integer) -> Int -> Word16
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Integer
    ra Integer -> Int -> Integer
    forall a. Bits a => a -> Int -> a
    `shiftR`)) [Int
    112, Int
    96 .. Int
    0]
        Cidr -> Maybe Cidr
    forall a. a -> Maybe a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Cidr -> Maybe Cidr)
    -> (NetAddress -> Cidr) -> NetAddress -> Maybe Cidr
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . NetAddress -> Cidr
    Cidr (NetAddress -> Maybe Cidr) -> NetAddress -> Maybe Cidr
    forall a b. (a -> b) -> a -> b
    $ V6HostAddress -> Word8 -> NetAddress
    NetAddress6 V6HostAddress
    ha Word8
    m
      where
        word :: Integer -> Word16
    word = Integer -> Word16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Integer -> Word16) -> (Integer -> Integer) -> Integer -> Word16
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Integer -> Integer -> Integer
    forall a. Bits a => a -> a -> a
    .&. Integer
    0xffff)
        fromList6 :: [Word16] -> V6HostAddress
    fromList6 [Word16]
    ws = Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> Word16
    -> V6HostAddress
    V6HostAddress Word16
    w0 Word16
    w1 Word16
    w2 Word16
    w3 Word16
    w4 Word16
    w5 Word16
    w6 Word16
    w7
          where [Word16
    w0, Word16
    w1, Word16
    w2, Word16
    w3, Word16
    w4, Word16
    w5, Word16
    w6, Word16
    w7] = [Word16]
    ws

    -- | Make Cidr type of IPv6 from host-address bits consistent with mask
    cidr6 :: V6HostAddress -> Word8 -> Maybe Cidr
    cidr6 :: V6HostAddress -> Word8 -> Maybe Cidr
    cidr6 V6HostAddress
    ha Word8
    m = do
      na <- V6HostAddress -> Word8 -> Maybe NetAddress
    netAddress6 V6HostAddress
    ha Word8
    m
      let (ma, ra) = maskCidr6 ha m
      guard $ ma == ra
      return $ Cidr na