+-- | Convert @addr@ to an 'Int' by converting each octet to an 'Int'
+-- and shifting the result to the left by 0,8.16, or 24 bits.
+ipv4address_to_int :: IPv4Address -> Int
+ipv4address_to_int addr =
+ (shifted_oct1) + (shifted_oct2) + (shifted_oct3) + oct4
+ where
+ oct1 = octet_to_int (octet1 addr)
+ oct2 = octet_to_int (octet2 addr)
+ oct3 = octet_to_int (octet3 addr)
+ oct4 = octet_to_int (octet4 addr)
+
+ shifted_oct1 = oct1 * 2^(24 :: Integer)
+ shifted_oct2 = oct2 * 2^(16 :: Integer)
+ shifted_oct3 = oct3 * 2^(8 :: Integer)
+
+
+
+-- | Convert an 'Int' @x@ to an 'IPv4Address'. Each octet of @x@ is
+-- right-shifted by the appropriate number of bits, and the fractional
+-- part is dropped.
+ipv4address_from_int :: Int -> Maybe IPv4Address
+ipv4address_from_int x
+ | (x < 0) || (x > 2^(32 :: Integer) - 1) = Nothing
+ | otherwise = do
+ -- If the algebra is right, none of these octet_from_int calls
+ -- below can fail since 0 <= x <= 2^32 - 1.
+ oct1 <- octet_from_int shifted_x1
+ oct2 <- octet_from_int shifted_x2
+ oct3 <- octet_from_int shifted_x3
+ oct4 <- octet_from_int x4
+ return $ IPv4Address oct1 oct2 oct3 oct4
+ where
+ -- Chop off the higher octets. x1 = x `mod` 2^32, would be
+ -- redundant.
+ x2 = x `mod` 2^(24 :: Integer)
+ x3 = x `mod` 2^(16 :: Integer)
+ x4 = x `mod` 2^(8 :: Integer)
+ -- Perform right-shifts. x4 doesn't need a shift.
+ shifted_x1 = x `quot` 2^(24 :: Integer)
+ shifted_x2 = x2 `quot` 2^(16 :: Integer)
+ shifted_x3 = x3 `quot` 2^(8 :: Integer)
+
+
+instance Enum IPv4Address where
+ -- We're supposed to throw a runtime error if you call (succ
+ -- maxBound), so the fromJust here doesn't introduce any additional
+ -- badness.
+ toEnum = fromJust . ipv4address_from_int
+ fromEnum = ipv4address_to_int