module Data.IP.Mask where

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

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

maskIPv6 :: Int -> IPv6
maskIPv6 :: Int -> IPv6
maskIPv6 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
$
                (Word64
0xffffffffffffffff, Word64
0xffffffffffffffff) (Word64, Word64) -> Int -> (Word64, Word64)
`shift128` (-Int
len)
  where
    bimapTup :: (t -> b) -> (t, t) -> (b, b)
bimapTup t -> b
f (t
x, 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 (Word64, Word64)
x Int
i
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = (Word64, Word64)
x (Word64, Word64) -> Int -> (Word64, Word64)
`shiftR128` (-Int
i)
    | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
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 (Word64
h, Word64
l) 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
- Int
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 (Word64
h, Word64
l) 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` (Int
64 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i))

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

toIP6Addr :: (Word64, Word64) -> IPv6Addr
toIP6Addr :: (Word64, Word64) -> IPv6Addr
toIP6Addr (Word64
h, Word64
l) =
    ( Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$ (Word64
h Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
32) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
m
    , Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$ Word64
h Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
m
    , Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
forall a b. (a -> b) -> a -> b
$ (Word64
l Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
32) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
m
    , Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Word32) -> Word64 -> Word32
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 = Word64
0xffffffff