module Data.Ip
( Ip ()
, readIp
, showIp
, fromOctets
, toOctets
, toWord32
) where
import Control.Applicative
import Data.Bits
import Data.List (intercalate)
import Data.Word
import Foreign
import Safe
newtype Ip = Ip {unIp :: Word32}
deriving (Eq, Ord, Bounded, Storable)
showIp :: Ip -> String
showIp ip = intercalate "." . map show $ [a, b, c, d]
where (a, b, c, d) = toOctets ip
readIp :: String -> Maybe Ip
readIp s = case octets' s of
[a, b, c, d] -> fromOctets <$> readMay a <*> readMay b
<*> readMay c <*> readMay d
_ -> Nothing
where
octets' os = case break (=='.') (dropWhile (=='.') os) of
("", _) -> []
(o, os') -> o : octets' os'
fromOctets :: Word8 -> Word8 -> Word8 -> Word8 -> Ip
fromOctets a b c d = Ip
$ (fromIntegral a `shiftL` 24)
.|. (fromIntegral b `shiftL` 16)
.|. (fromIntegral c `shiftL` 8)
.|. (fromIntegral d)
toOctets :: Ip -> (Word8, Word8, Word8, Word8)
toOctets (Ip word) = (byte 3 word, byte 2 word, byte 1 word, byte 0 word)
where
byte i w = fromIntegral (w `shiftR` (i * 8))
toWord32 :: Ip -> Word32
toWord32 = unIp