    module Network.Wai.Logger.IP (
        NumericAddress, showSockAddr
      ) where

    import Data.Bits (shift, (.&.))
    import Data.Word (Word32)
    import Network.Socket (SockAddr(..))
    import System.ByteOrder (ByteOrder(..), byteOrder)
    import Text.Printf (printf)

    -- |  A type for IP address in numeric string representation.
    type NumericAddress = String

    showIPv4 :: Word32 -> Bool -> NumericAddress
    showIPv4 :: Word32 -> Bool -> NumericAddress
    showIPv4 w32 :: Word32
    w32 little :: Bool
    little
        | Bool
    little    = Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b1 NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ "." NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b2 NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ "." NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b3 NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ "." NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b4
        | Bool
    otherwise = Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b4 NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ "." NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b3 NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ "." NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b2 NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ "." NumericAddress -> NumericAddress -> NumericAddress
    forall a. [a] -> [a] -> [a]
    ++ Word32 -> NumericAddress
    forall a. Show a => a -> NumericAddress
    show Word32
    b1
      where
        t1 :: Word32
    t1 = Word32
    w32
        t2 :: Word32
    t2 = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shift Word32
    t1 (-8)
        t3 :: Word32
    t3 = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shift Word32
    t2 (-8)
        t4 :: Word32
    t4 = Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    shift Word32
    t3 (-8)
        b1 :: Word32
    b1 = Word32
    t1 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. 0x000000ff
        b2 :: Word32
    b2 = Word32
    t2 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. 0x000000ff
        b3 :: Word32
    b3 = Word32
    t3 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. 0x000000ff
        b4 :: Word32
    b4 = Word32
    t4 Word32 -> Word32 -> Word32
    forall a. Bits a => a -> a -> a
    .&. 0x000000ff

    showIPv6 :: (Word32,Word32,Word32,Word32) -> String
    showIPv6 :: (Word32, Word32, Word32, Word32) -> NumericAddress
    showIPv6 (w1 :: Word32
    w1,w2 :: Word32
    w2,w3 :: Word32
    w3,w4 :: Word32
    w4) =
        NumericAddress
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> NumericAddress
    forall r. PrintfType r => NumericAddress -> r
    printf "%x:%x:%x:%x:%x:%x:%x:%x" Word32
    s1 Word32
    s2 Word32
    s3 Word32
    s4 Word32
    s5 Word32
    s6 Word32
    s7 Word32
    s8
      where
        (s1 :: Word32
    s1,s2 :: Word32
    s2) = Word32 -> (Word32, Word32)
    forall a. (Bits a, Num a) => a -> (a, a)
    split16 Word32
    w1
        (s3 :: Word32
    s3,s4 :: Word32
    s4) = Word32 -> (Word32, Word32)
    forall a. (Bits a, Num a) => a -> (a, a)
    split16 Word32
    w2
        (s5 :: Word32
    s5,s6 :: Word32
    s6) = Word32 -> (Word32, Word32)
    forall a. (Bits a, Num a) => a -> (a, a)
    split16 Word32
    w3
        (s7 :: Word32
    s7,s8 :: Word32
    s8) = Word32 -> (Word32, Word32)
    forall a. (Bits a, Num a) => a -> (a, a)
    split16 Word32
    w4
        split16 :: a -> (a, a)
    split16 w :: a
    w = (a
    h1,a
    h2)
          where
            h1 :: a
    h1 = a -> Int -> a
    forall a. Bits a => a -> Int -> a
    shift a
    w (-16) a -> a -> a
    forall a. Bits a => a -> a -> a
    .&. 0x0000ffff
            h2 :: a
    h2 = a
    w a -> a -> a
    forall a. Bits a => a -> a -> a
    .&. 0x0000ffff
    -- | Convert 'SockAddr' to 'NumericAddress'. If the address is
    --   IPv4-embedded IPv6 address, the IPv4 is extracted.
    showSockAddr :: SockAddr -> NumericAddress
    -- HostAddr is network byte order.
    showSockAddr :: SockAddr -> NumericAddress
    showSockAddr (SockAddrInet _ addr4 :: Word32
    addr4)                       = Word32 -> Bool -> NumericAddress
    showIPv4 Word32
    addr4 (ByteOrder
    byteOrder ByteOrder -> ByteOrder -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteOrder
    LittleEndian)
    -- HostAddr6 is host byte order.
    showSockAddr (SockAddrInet6 _ _ (0,0,0x0000ffff,addr4 :: Word32
    addr4) _) = Word32 -> Bool -> NumericAddress
    showIPv4 Word32
    addr4 Bool
    False
    showSockAddr (SockAddrInet6 _ _ (0,0,0,1) _)              = "::1"
    showSockAddr (SockAddrInet6 _ _ addr6 :: (Word32, Word32, Word32, Word32)
    addr6 _)                  = (Word32, Word32, Word32, Word32) -> NumericAddress
    showIPv6 (Word32, Word32, Word32, Word32)
    addr6
    showSockAddr _                                            = "unknownSocket"