    module Data.IP.Mask where

    import Data.Bits
    import Data.IP.Addr
    import Data.Word

    maskIPv4 :: Int -> IPv4
    maskIPv4 :: Int -> IPv4
    maskIPv4 len :: Int
    len =
        IPv4Addr -> IPv4
    IP4 (IPv4Addr -> IPv4) -> IPv4Addr -> IPv4
    forall a b. (a -> b) -> a -> b
    $ IPv4Addr -> IPv4Addr
    forall a. Bits a => a -> a
    complement (IPv4Addr -> IPv4Addr) -> IPv4Addr -> IPv4Addr
    forall a b. (a -> b) -> a -> b
    $ 0xffffffff IPv4Addr -> Int -> IPv4Addr
    forall a. Bits a => a -> Int -> a
    `shift` (-Int
    len)

    maskIPv6 :: Int -> IPv6
    maskIPv6 :: Int -> IPv6
    maskIPv6 len :: Int
    len =
        IPv6Addr -> IPv6
    IP6 (IPv6Addr -> IPv6) -> IPv6Addr -> IPv6
    forall a b. (a -> b) -> a -> b
    $ (Word64, Word64) -> IPv6Addr
    toIP6Addr ((Word64, Word64) -> IPv6Addr) -> (Word64, Word64) -> IPv6Addr
    forall a b. (a -> b) -> a -> b
    $ (Word64 -> Word64) -> (Word64, Word64) -> (Word64, Word64)
    forall t b. (t -> b) -> (t, t) -> (b, b)
    bimapTup Word64 -> Word64
    forall a. Bits a => a -> a
    complement ((Word64, Word64) -> (Word64, Word64))
    -> (Word64, Word64) -> (Word64, Word64)
    forall a b. (a -> b) -> a -> b
    $
                (0xffffffffffffffff, 0xffffffffffffffff) (Word64, Word64) -> Int -> (Word64, Word64)
    `shift128` (-Int
    len)
     where
       bimapTup :: (t -> b) -> (t, t) -> (b, b)
    bimapTup f :: t -> b
    f (x :: t
    x,y :: t
    y) = (t -> b
    f t
    x, t -> b
    f t
    y)

    shift128 :: (Word64, Word64) -> Int -> (Word64, Word64)
    shift128 :: (Word64, Word64) -> Int -> (Word64, Word64)
    shift128 x :: (Word64, Word64)
    x i :: Int
    i
        | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0  = (Word64, Word64)
    x (Word64, Word64) -> Int -> (Word64, Word64)
    `shiftR128` (-Int
    i)
        | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > 0  = (Word64, Word64)
    x (Word64, Word64) -> Int -> (Word64, Word64)
    `shiftL128` Int
    i
        | Bool
    otherwise = (Word64, Word64)
    x

    shiftL128 :: (Word64, Word64) -> Int -> (Word64, Word64)
    shiftL128 :: (Word64, Word64) -> Int -> (Word64, Word64)
    shiftL128 (h :: Word64
    h, l :: Word64
    l) i :: Int
    i =
            ( (Word64
    h Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    i) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. (Word64
    l Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shift` (Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - 64) ), (Word64
    l Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    i))

    shiftR128 :: (Word64, Word64) -> Int -> (Word64, Word64)
    shiftR128 :: (Word64, Word64) -> Int -> (Word64, Word64)
    shiftR128 (h :: Word64
    h, l :: Word64
    l) i :: Int
    i =
        (Word64
    h Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    i, (Word64
    l Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    i) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. Word64
    h Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shift` (64 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    i) )

    fromIP6Addr :: IPv6Addr -> (Word64, Word64)
    fromIP6Addr :: IPv6Addr -> (Word64, Word64)
    fromIP6Addr (w3 :: IPv4Addr
    w3, w2 :: IPv4Addr
    w2, w1 :: IPv4Addr
    w1, w0 :: IPv4Addr
    w0) =
       ( (IPv4Addr -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral IPv4Addr
    w3 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` 32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. IPv4Addr -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral IPv4Addr
    w2
       , (IPv4Addr -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral IPv4Addr
    w1 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` 32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. IPv4Addr -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral IPv4Addr
    w0
       )

    toIP6Addr :: (Word64, Word64) -> IPv6Addr
    toIP6Addr :: (Word64, Word64) -> IPv6Addr
    toIP6Addr (h :: Word64
    h, l :: Word64
    l) =
        ( Word64 -> IPv4Addr
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64 -> IPv4Addr) -> Word64 -> IPv4Addr
    forall a b. (a -> b) -> a -> b
    $ (Word64
    h Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` 32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    m
        , Word64 -> IPv4Addr
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64 -> IPv4Addr) -> Word64 -> IPv4Addr
    forall a b. (a -> b) -> a -> b
    $ Word64
    h Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    m
        , Word64 -> IPv4Addr
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64 -> IPv4Addr) -> Word64 -> IPv4Addr
    forall a b. (a -> b) -> a -> b
    $ (Word64
    l Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` 32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    m
        , Word64 -> IPv4Addr
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64 -> IPv4Addr) -> Word64 -> IPv4Addr
    forall a b. (a -> b) -> a -> b
    $ Word64
    l Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    m
        )
      where m :: Word64
    m = 0xffffffff