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 forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> a
complement forall a b. (a -> b) -> a -> b
$ Word32
0xffffffff forall a. Bits a => a -> Int -> a
`shift` (-Int
len)

maskIPv6 :: Int -> IPv6
maskIPv6 :: Int -> IPv6
maskIPv6 Int
len =
    IPv6Addr -> IPv6
IP6 forall a b. (a -> b) -> a -> b
$ (Word64, Word64) -> IPv6Addr
toIP6Addr forall a b. (a -> b) -> a -> b
$ forall {t} {b}. (t -> b) -> (t, t) -> (b, b)
bimapTup forall a. Bits a => a -> a
complement 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 forall a. Ord a => a -> a -> Bool
< Int
0  = (Word64, Word64)
x (Word64, Word64) -> Int -> (Word64, Word64)
`shiftR128` (-Int
i)
    | Int
i 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 forall a. Bits a => a -> Int -> a
`shiftL` Int
i) forall a. Bits a => a -> a -> a
.|. (Word64
l forall a. Bits a => a -> Int -> a
`shift` (Int
i forall a. Num a => a -> a -> a
- Int
64) ), (Word64
l 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 forall a. Bits a => a -> Int -> a
`shiftR` Int
i, (Word64
l forall a. Bits a => a -> Int -> a
`shiftR` Int
i) forall a. Bits a => a -> a -> a
.|. Word64
h forall a. Bits a => a -> Int -> a
`shift` (Int
64 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) =
   ( (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w3 forall a. Bits a => a -> Int -> a
`shiftL` Int
32) forall a. Bits a => a -> a -> a
.|. forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w2
   , (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
w1 forall a. Bits a => a -> Int -> a
`shiftL` Int
32) forall a. Bits a => a -> a -> a
.|. 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) =
    ( forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Word64
h forall a. Bits a => a -> Int -> a
`shiftR` Int
32) forall a. Bits a => a -> a -> a
.&. Word64
m
    , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word64
h forall a. Bits a => a -> a -> a
.&. Word64
m
    , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ (Word64
l forall a. Bits a => a -> Int -> a
`shiftR` Int
32) forall a. Bits a => a -> a -> a
.&. Word64
m
    , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ Word64
l forall a. Bits a => a -> a -> a
.&. Word64
m
    )
  where m :: Word64
m = Word64
0xffffffff