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

    showIPv6 :: (Word32,Word32,Word32,Word32) -> String
    showIPv6 :: (Word32, Word32, Word32, Word32) -> String
    showIPv6 (Word32
    w1,Word32
    w2,Word32
    w3,Word32
    w4) =
        String
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> Word32
    -> String
    forall r. PrintfType r => String -> r
    printf String
    "%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
        (Word32
    s1,Word32
    s2) = Word32 -> (Word32, Word32)
    forall {b}. (Bits b, Num b) => b -> (b, b)
    split16 Word32
    w1
        (Word32
    s3,Word32
    s4) = Word32 -> (Word32, Word32)
    forall {b}. (Bits b, Num b) => b -> (b, b)
    split16 Word32
    w2
        (Word32
    s5,Word32
    s6) = Word32 -> (Word32, Word32)
    forall {b}. (Bits b, Num b) => b -> (b, b)
    split16 Word32
    w3
        (Word32
    s7,Word32
    s8) = Word32 -> (Word32, Word32)
    forall {b}. (Bits b, Num b) => b -> (b, b)
    split16 Word32
    w4
        split16 :: b -> (b, b)
    split16 b
    w = (b
    h1,b
    h2)
          where
            h1 :: b
    h1 = b -> Int -> b
    forall a. Bits a => a -> Int -> a
    shift b
    w (-Int
    16) b -> b -> b
    forall a. Bits a => a -> a -> a
    .&. b
    0x0000ffff
            h2 :: b
    h2 = b
    w b -> b -> b
    forall a. Bits a => a -> a -> a
    .&. b
    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 -> String
    showSockAddr (SockAddrInet PortNumber
    _ Word32
    addr4)                       = Word32 -> Bool -> String
    showIPv4 Word32
    addr4 (ByteOrder
    byteOrder ByteOrder -> ByteOrder -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteOrder
    LittleEndian)
    -- HostAddr6 is host byte order.
    showSockAddr (SockAddrInet6 PortNumber
    _ Word32
    _ (Word32
    0,Word32
    0,Word32
    0x0000ffff,Word32
    addr4) Word32
    _) = Word32 -> Bool -> String
    showIPv4 Word32
    addr4 Bool
    False
    showSockAddr (SockAddrInet6 PortNumber
    _ Word32
    _ (Word32
    0,Word32
    0,Word32
    0,Word32
    1) Word32
    _)              = String
    "::1"
    showSockAddr (SockAddrInet6 PortNumber
    _ Word32
    _ (Word32, Word32, Word32, Word32)
    addr6 Word32
    _)                  = (Word32, Word32, Word32, Word32) -> String
    showIPv6 (Word32, Word32, Word32, Word32)
    addr6
    showSockAddr (SockAddrUnix String
    _)                             = String
    "-"