    {-# LINE 1 "src/Network/Info.hsc" #-}
    {-# LANGUAGE ForeignFunctionInterface #-}

    module Network.Info (
        getNetworkInterfaces,
        NetworkInterface (..),
        IPv4 (..),
        IPv6 (..),
        MAC (..),
    ) where

    import Data.Bits ((.&.), shiftR, shiftL)
    import Data.List (intersperse)
    import Data.Word
    import Foreign.C.String
    import Foreign.C.Types
    import Foreign.Marshal.Array
    import Foreign.Ptr
    import Foreign.Storable
    import Numeric (showHex)
    import Text.Printf

    ----------------------------------------------------------------------
    -- FFI
    ----------------------------------------------------------------------

    foreign import ccall unsafe "c_get_network_interfaces"
            c_get_network_interfaces :: Ptr NetworkInterface -> CInt -> IO CInt

    ----------------------------------------------------------------------
    -- Network interfaces
    ----------------------------------------------------------------------

    -- | Describes the basic configuration of a network interface. /This/
    --   /definition is currently limited to just one address per family./
    data NetworkInterface = NetworkInterface
        { NetworkInterface -> String
    name :: String -- ^ Interface name (e.g. \"eth0\", \"lo\", \"Local Area Connection\")
        , NetworkInterface -> IPv4
    ipv4 :: IPv4   -- ^ IPv4 address
        , NetworkInterface -> IPv6
    ipv6 :: IPv6   -- ^ IPv6 address
        , NetworkInterface -> MAC
    mac  :: MAC    -- ^ MAC address
        } deriving (Int -> NetworkInterface -> ShowS
    [NetworkInterface] -> ShowS
    NetworkInterface -> String
    (Int -> NetworkInterface -> ShowS)
    -> (NetworkInterface -> String)
    -> ([NetworkInterface] -> ShowS)
    -> Show NetworkInterface
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [NetworkInterface] -> ShowS
    $cshowList :: [NetworkInterface] -> ShowS
    show :: NetworkInterface -> String
    $cshow :: NetworkInterface -> String
    showsPrec :: Int -> NetworkInterface -> ShowS
    $cshowsPrec :: Int -> NetworkInterface -> ShowS
    Show)

    instance Storable NetworkInterface where
        alignment :: NetworkInterface -> Int
    alignment _ = 8
    {-# LINE 48 "src/Network/Info.hsc" #-}
        sizeOf _    = (576)
    {-# LINE 49 "src/Network/Info.hsc" #-}
        peek ptr    = do
            name <- peekCWString $ ((\hsc_ptr -> hsc_ptr `plusPtr` 0)) ptr
    {-# LINE 51 "src/Network/Info.hsc" #-}
            ipv4 <- ((\hsc_ptr -> peekByteOff hsc_ptr 528)) ptr
    {-# LINE 52 "src/Network/Info.hsc" #-}
            ipv6 <- ((\hsc_ptr -> peekByteOff hsc_ptr 536)) ptr
    {-# LINE 53 "src/Network/Info.hsc" #-}
            mac  <- ((\hsc_ptr -> peekByteOff hsc_ptr 568)) ptr
    {-# LINE 54 "src/Network/Info.hsc" #-}
            return $ NetworkInterface name ipv4 ipv6 mac

    -- | Gets the address information for each of the network interfaces on
    --   the local computer.
    getNetworkInterfaces :: IO [NetworkInterface]
    getNetworkInterfaces :: IO [NetworkInterface]
    getNetworkInterfaces =
        Int
    -> (Ptr NetworkInterface -> IO [NetworkInterface])
    -> IO [NetworkInterface]
    forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
    allocaArray 64 ((Ptr NetworkInterface -> IO [NetworkInterface])
     -> IO [NetworkInterface])
    -> (Ptr NetworkInterface -> IO [NetworkInterface])
    -> IO [NetworkInterface]
    forall a b. (a -> b) -> a -> b
    $ \ptr :: Ptr NetworkInterface
    ptr -> do
        CInt
    count <- Ptr NetworkInterface -> CInt -> IO CInt
    c_get_network_interfaces Ptr NetworkInterface
    ptr 64
        Int -> Ptr NetworkInterface -> IO [NetworkInterface]
    forall a. Storable a => Int -> Ptr a -> IO [a]
    peekArray (CInt -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral CInt
    count) Ptr NetworkInterface
    ptr

    ----------------------------------------------------------------------
    -- IPv4 addresses
    ----------------------------------------------------------------------

    -- | Represents an IPv4 address (e.g. @172.23.21.1@, @127.0.0.1@)
    data IPv4 = IPv4
        {-# UNPACK #-} !Word32
        deriving (IPv4 -> IPv4 -> Bool
    (IPv4 -> IPv4 -> Bool) -> (IPv4 -> IPv4 -> Bool) -> Eq IPv4
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: IPv4 -> IPv4 -> Bool
    $c/= :: IPv4 -> IPv4 -> Bool
    == :: IPv4 -> IPv4 -> Bool
    $c== :: IPv4 -> IPv4 -> Bool
    Eq, Eq IPv4
    Eq IPv4 =>
    (IPv4 -> IPv4 -> Ordering)
    -> (IPv4 -> IPv4 -> Bool)
    -> (IPv4 -> IPv4 -> Bool)
    -> (IPv4 -> IPv4 -> Bool)
    -> (IPv4 -> IPv4 -> Bool)
    -> (IPv4 -> IPv4 -> IPv4)
    -> (IPv4 -> IPv4 -> IPv4)
    -> Ord IPv4
    IPv4 -> IPv4 -> Bool
    IPv4 -> IPv4 -> Ordering
    IPv4 -> IPv4 -> IPv4
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: IPv4 -> IPv4 -> IPv4
    $cmin :: IPv4 -> IPv4 -> IPv4
    max :: IPv4 -> IPv4 -> IPv4
    $cmax :: IPv4 -> IPv4 -> IPv4
    >= :: IPv4 -> IPv4 -> Bool
    $c>= :: IPv4 -> IPv4 -> Bool
    > :: IPv4 -> IPv4 -> Bool
    $c> :: IPv4 -> IPv4 -> Bool
    <= :: IPv4 -> IPv4 -> Bool
    $c<= :: IPv4 -> IPv4 -> Bool
    < :: IPv4 -> IPv4 -> Bool
    $c< :: IPv4 -> IPv4 -> Bool
    compare :: IPv4 -> IPv4 -> Ordering
    $ccompare :: IPv4 -> IPv4 -> Ordering
    $cp1Ord :: Eq IPv4
    Ord, IPv4
    IPv4 -> IPv4 -> Bounded IPv4
    forall a. a -> a -> Bounded a
    maxBound :: IPv4
    $cmaxBound :: IPv4
    minBound :: IPv4
    $cminBound :: IPv4
    Bounded)

    instance Show IPv4 where
        show :: IPv4 -> String
    show = IPv4 -> String
    showIPv4

    instance Storable IPv4 where
        alignment :: IPv4 -> Int
    alignment _ = 1
        sizeOf :: IPv4 -> Int
    sizeOf _    = 4
        peek :: Ptr IPv4 -> IO IPv4
    peek p :: Ptr IPv4
    p      = do
            Word32
    ip <- Ptr Word32 -> IO Word32
    forall a. Storable a => Ptr a -> IO a
    peek (Ptr IPv4 -> Ptr Word32
    forall a b. Ptr a -> Ptr b
    castPtr Ptr IPv4
    p)
            IPv4 -> IO IPv4
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Word32 -> IPv4
    IPv4 Word32
    ip)
        poke :: Ptr IPv4 -> IPv4 -> IO ()
    poke p :: Ptr IPv4
    p (IPv4 ip :: Word32
    ip) =
            Ptr Word32 -> Word32 -> IO ()
    forall a. Storable a => Ptr a -> a -> IO ()
    poke (Ptr IPv4 -> Ptr Word32
    forall a b. Ptr a -> Ptr b
    castPtr Ptr IPv4
    p) Word32
    ip

    ----------------------------------------------------------------------
    -- IPv6 addresses
    ----------------------------------------------------------------------

    -- | Represents an IPv6 address (e.g. @2001:db8:85a3::8a2e:370:7334@, @::1@)
    data IPv6 = IPv6
        {-# UNPACK #-} !Word32
        {-# UNPACK #-} !Word32
        {-# UNPACK #-} !Word32
        {-# UNPACK #-} !Word32
        deriving (IPv6 -> IPv6 -> Bool
    (IPv6 -> IPv6 -> Bool) -> (IPv6 -> IPv6 -> Bool) -> Eq IPv6
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: IPv6 -> IPv6 -> Bool
    $c/= :: IPv6 -> IPv6 -> Bool
    == :: IPv6 -> IPv6 -> Bool
    $c== :: IPv6 -> IPv6 -> Bool
    Eq, Eq IPv6
    Eq IPv6 =>
    (IPv6 -> IPv6 -> Ordering)
    -> (IPv6 -> IPv6 -> Bool)
    -> (IPv6 -> IPv6 -> Bool)
    -> (IPv6 -> IPv6 -> Bool)
    -> (IPv6 -> IPv6 -> Bool)
    -> (IPv6 -> IPv6 -> IPv6)
    -> (IPv6 -> IPv6 -> IPv6)
    -> Ord IPv6
    IPv6 -> IPv6 -> Bool
    IPv6 -> IPv6 -> Ordering
    IPv6 -> IPv6 -> IPv6
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: IPv6 -> IPv6 -> IPv6
    $cmin :: IPv6 -> IPv6 -> IPv6
    max :: IPv6 -> IPv6 -> IPv6
    $cmax :: IPv6 -> IPv6 -> IPv6
    >= :: IPv6 -> IPv6 -> Bool
    $c>= :: IPv6 -> IPv6 -> Bool
    > :: IPv6 -> IPv6 -> Bool
    $c> :: IPv6 -> IPv6 -> Bool
    <= :: IPv6 -> IPv6 -> Bool
    $c<= :: IPv6 -> IPv6 -> Bool
    < :: IPv6 -> IPv6 -> Bool
    $c< :: IPv6 -> IPv6 -> Bool
    compare :: IPv6 -> IPv6 -> Ordering
    $ccompare :: IPv6 -> IPv6 -> Ordering
    $cp1Ord :: Eq IPv6
    Ord, IPv6
    IPv6 -> IPv6 -> Bounded IPv6
    forall a. a -> a -> Bounded a
    maxBound :: IPv6
    $cmaxBound :: IPv6
    minBound :: IPv6
    $cminBound :: IPv6
    Bounded)

    -- | Not yet capable of collapsing groups of zeros, will still
    --   generate valid addresses however.
    instance Show IPv6 where
        show :: IPv6 -> String
    show = IPv6 -> String
    showIPv6

    instance Storable IPv6 where
        alignment :: IPv6 -> Int
    alignment _ = 1
        sizeOf :: IPv6 -> Int
    sizeOf _    = 16
        peek :: Ptr IPv6 -> IO IPv6
    peek p :: Ptr IPv6
    p      = do
            let ptr :: Ptr b
    ptr = Ptr IPv6 -> Ptr b
    forall a b. Ptr a -> Ptr b
    castPtr Ptr IPv6
    p
            Word32
    a <- Ptr Word32 -> Int -> IO Word32
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr Word32
    forall b. Ptr b
    ptr 0
            Word32
    b <- Ptr Word32 -> Int -> IO Word32
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr Word32
    forall b. Ptr b
    ptr 1
            Word32
    c <- Ptr Word32 -> Int -> IO Word32
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr Word32
    forall b. Ptr b
    ptr 2
            Word32
    d <- Ptr Word32 -> Int -> IO Word32
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr Word32
    forall b. Ptr b
    ptr 3
            IPv6 -> IO IPv6
    forall (m :: * -> *) a. Monad m => a -> m a
    return (IPv6 -> IO IPv6) -> IPv6 -> IO IPv6
    forall a b. (a -> b) -> a -> b
    $ Word32 -> Word32 -> Word32 -> Word32 -> IPv6
    IPv6 Word32
    a Word32
    b Word32
    c Word32
    d
        poke :: Ptr IPv6 -> IPv6 -> IO ()
    poke p :: Ptr IPv6
    p (IPv6 a :: Word32
    a b :: Word32
    b c :: Word32
    c d :: Word32
    d) = do
            let ptr :: Ptr b
    ptr = Ptr IPv6 -> Ptr b
    forall a b. Ptr a -> Ptr b
    castPtr Ptr IPv6
    p
            Ptr Word32 -> Int -> Word32 -> IO ()
    forall a. Storable a => Ptr a -> Int -> a -> IO ()
    pokeElemOff Ptr Word32
    forall b. Ptr b
    ptr 0 Word32
    a
            Ptr Word32 -> Int -> Word32 -> IO ()
    forall a. Storable a => Ptr a -> Int -> a -> IO ()
    pokeElemOff Ptr Word32
    forall b. Ptr b
    ptr 1 Word32
    b
            Ptr Word32 -> Int -> Word32 -> IO ()
    forall a. Storable a => Ptr a -> Int -> a -> IO ()
    pokeElemOff Ptr Word32
    forall b. Ptr b
    ptr 2 Word32
    c
            Ptr Word32 -> Int -> Word32 -> IO ()
    forall a. Storable a => Ptr a -> Int -> a -> IO ()
    pokeElemOff Ptr Word32
    forall b. Ptr b
    ptr 3 Word32
    d

    ----------------------------------------------------------------------
    -- MAC addresses
    ----------------------------------------------------------------------

    -- | Represents a MAC address (e.g. @01:23:45:67:89:ab@)
    data MAC = MAC
        {-# UNPACK #-} !Word8
        {-# UNPACK #-} !Word8
        {-# UNPACK #-} !Word8
        {-# UNPACK #-} !Word8
        {-# UNPACK #-} !Word8
        {-# UNPACK #-} !Word8
        deriving (MAC -> MAC -> Bool
    (MAC -> MAC -> Bool) -> (MAC -> MAC -> Bool) -> Eq MAC
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: MAC -> MAC -> Bool
    $c/= :: MAC -> MAC -> Bool
    == :: MAC -> MAC -> Bool
    $c== :: MAC -> MAC -> Bool
    Eq, Eq MAC
    Eq MAC =>
    (MAC -> MAC -> Ordering)
    -> (MAC -> MAC -> Bool)
    -> (MAC -> MAC -> Bool)
    -> (MAC -> MAC -> Bool)
    -> (MAC -> MAC -> Bool)
    -> (MAC -> MAC -> MAC)
    -> (MAC -> MAC -> MAC)
    -> Ord MAC
    MAC -> MAC -> Bool
    MAC -> MAC -> Ordering
    MAC -> MAC -> MAC
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: MAC -> MAC -> MAC
    $cmin :: MAC -> MAC -> MAC
    max :: MAC -> MAC -> MAC
    $cmax :: MAC -> MAC -> MAC
    >= :: MAC -> MAC -> Bool
    $c>= :: MAC -> MAC -> Bool
    > :: MAC -> MAC -> Bool
    $c> :: MAC -> MAC -> Bool
    <= :: MAC -> MAC -> Bool
    $c<= :: MAC -> MAC -> Bool
    < :: MAC -> MAC -> Bool
    $c< :: MAC -> MAC -> Bool
    compare :: MAC -> MAC -> Ordering
    $ccompare :: MAC -> MAC -> Ordering
    $cp1Ord :: Eq MAC
    Ord, MAC
    MAC -> MAC -> Bounded MAC
    forall a. a -> a -> Bounded a
    maxBound :: MAC
    $cmaxBound :: MAC
    minBound :: MAC
    $cminBound :: MAC
    Bounded)

    instance Show MAC where
        show :: MAC -> String
    show (MAC a :: Word8
    a b :: Word8
    b c :: Word8
    c d :: Word8
    d e :: Word8
    e f :: Word8
    f) = String
    -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> String
    forall r. PrintfType r => String -> r
    printf "%02x:%02x:%02x:%02x:%02x:%02x" Word8
    a Word8
    b Word8
    c Word8
    d Word8
    e Word8
    f

    instance Storable MAC where
        alignment :: MAC -> Int
    alignment _ = 1
        sizeOf :: MAC -> Int
    sizeOf _    = 6
        peek :: Ptr MAC -> IO MAC
    peek p :: Ptr MAC
    p      = do
            Word8
    a <- Ptr Word8 -> IO Word8
    forall a. Storable a => Ptr a -> IO a
    peek (Ptr Word8 -> IO Word8) -> Ptr Word8 -> IO Word8
    forall a b. (a -> b) -> a -> b
    $ Ptr MAC -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr MAC
    p
            Word8
    b <- Ptr MAC -> Int -> IO Word8
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr MAC
    p 1
            Word8
    c <- Ptr MAC -> Int -> IO Word8
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr MAC
    p 2
            Word8
    d <- Ptr MAC -> Int -> IO Word8
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr MAC
    p 3
            Word8
    e <- Ptr MAC -> Int -> IO Word8
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr MAC
    p 4
            Word8
    f <- Ptr MAC -> Int -> IO Word8
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr MAC
    p 5
            MAC -> IO MAC
    forall (m :: * -> *) a. Monad m => a -> m a
    return (MAC -> IO MAC) -> MAC -> IO MAC
    forall a b. (a -> b) -> a -> b
    $ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> MAC
    MAC Word8
    a Word8
    b Word8
    c Word8
    d Word8
    e Word8
    f
        poke :: Ptr MAC -> MAC -> IO ()
    poke p :: Ptr MAC
    p (MAC a :: Word8
    a b :: Word8
    b c :: Word8
    c d :: Word8
    d e :: Word8
    e f :: Word8
    f) = do
            Ptr Word8 -> Word8 -> IO ()
    forall a. Storable a => Ptr a -> a -> IO ()
    poke (Ptr MAC -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr MAC
    p) Word8
    a
            Ptr MAC -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr MAC
    p 1 Word8
    b
            Ptr MAC -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr MAC
    p 2 Word8
    c
            Ptr MAC -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr MAC
    p 3 Word8
    d
            Ptr MAC -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr MAC
    p 4 Word8
    e
            Ptr MAC -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr MAC
    p 5 Word8
    f

    ----------------------------------------------------------------------
    -- Helper functions
    ----------------------------------------------------------------------

    showIPv4 :: IPv4 -> String
    showIPv4 :: IPv4 -> String
    showIPv4 (IPv4 ip :: Word32
    ip) = [String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat ([String] -> String)
    -> ([String] -> [String]) -> [String] -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    intersperse "." ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ [String]
    showOctets
      where
        showOctets :: [String]
    showOctets = (Word8 -> String) -> [Word8] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map Word8 -> String
    forall a. Show a => a -> String
    show ([Word8] -> [String]) -> [Word8] -> [String]
    forall a b. (a -> b) -> a -> b
    $ Word32 -> [Word8]
    word8s Word32
    ip

    -- TODO: drop out consecutive zeros
    showIPv6 :: IPv6 -> String
    showIPv6 :: IPv6 -> String
    showIPv6 (IPv6 a :: Word32
    a b :: Word32
    b c :: Word32
    c d :: Word32
    d) = ([String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat ([String] -> String)
    -> ([String] -> [String]) -> [String] -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    intersperse ":") [String]
    groups
      where
        groups :: [String]
    groups = (Word16 -> String) -> [Word16] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Word16 -> ShowS) -> String -> Word16 -> String
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Word16 -> ShowS
    forall a. (Integral a, Show a) => a -> ShowS
    showHex "")  ([Word16] -> [String]) -> [Word16] -> [String]
    forall a b. (a -> b) -> a -> b
    $ (Word32 -> [Word16]) -> [Word32] -> [Word16]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ([Word8] -> [Word16]
    group ([Word8] -> [Word16]) -> (Word32 -> [Word8]) -> Word32 -> [Word16]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word32 -> [Word8]
    word8s) [Word32
    a,Word32
    b,Word32
    c,Word32
    d]

    word8s :: Word32 -> [Word8]
    word8s :: Word32 -> [Word8]
    word8s x :: Word32
    x = [ Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> Word32 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word32
    x
               , Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> Word32 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word32
    x Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftR` 8
               , Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> Word32 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word32
    x Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftR` 16
               , Word32 -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word32 -> Word8) -> Word32 -> Word8
    forall a b. (a -> b) -> a -> b
    $ Word32
    x Word32 -> Int -> Word32
    forall a. Bits a => a -> Int -> a
    `shiftR` 24 ]

    group :: [Word8] -> [Word16]
    group :: [Word8] -> [Word16]
    group = (Word8 -> Word8 -> Word16) -> [Word8] -> [Word16]
    forall a b. (a -> a -> b) -> [a] -> [b]
    map2 ((Word8 -> Word8 -> Word16) -> [Word8] -> [Word16])
    -> (Word8 -> Word8 -> Word16) -> [Word8] -> [Word16]
    forall a b. (a -> b) -> a -> b
    $ \x :: Word8
    x y :: Word8
    y -> (Word8 -> Word16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    x) Word16 -> Int -> Word16
    forall a. Bits a => a -> Int -> a
    `shiftL` 8 Word16 -> Word16 -> Word16
    forall a. Num a => a -> a -> a
    + (Word8 -> Word16
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    y)

    map2 :: (a -> a -> b) -> [a] -> [b]
    map2 :: (a -> a -> b) -> [a] -> [b]
    map2 _ [] = []
    map2 f :: a -> a -> b
    f (x :: a
    x:y :: a
    y:zs :: [a]
    zs) = a -> a -> b
    f a
    x a
    y b -> [b] -> [b]
    forall a. a -> [a] -> [a]
    : (a -> a -> b) -> [a] -> [b]
    forall a b. (a -> a -> b) -> [a] -> [b]
    map2 a -> a -> b
    f [a]
    zs