    -- | Byte-level coding utility functions.
    --   Plain forms are big-endian, little-endian forms have @_le@ suffix.
    module Sound.OSC.Coding.Byte where

    import Data.Bits {- base -}
    import Data.Int {- base -}
    import Data.Word {- base -}
    import System.IO {- base -}

    import qualified Data.Binary as Binary {- binary -}
    import qualified Data.Binary.Get as Get {- binary -}
    import qualified Data.Binary.Put as Put {- binary -}
    import qualified Data.ByteString as S {- bytestring -}
    import qualified Data.ByteString.Char8 as S.C {- bytestring -}
    import qualified Data.ByteString.Lazy as L {- bytestring -}
    import qualified Data.ByteString.Lazy.Char8 as L.C {- bytestring -}

    import qualified Sound.OSC.Coding.Cast as Cast {- hosc -}
    import Sound.OSC.Coding.Convert {- hosc -}

    -- * Encode

    -- | Encode a signed 8-bit integer.
    encode_i8 :: Int -> L.ByteString
    encode_i8 :: Int -> ByteString
    encode_i8 = Int8 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode (Int8 -> ByteString) -> (Int -> Int8) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Int8
    int_to_int8

    -- | Encode an un-signed 8-bit integer.
    encode_u8 :: Int -> L.ByteString
    encode_u8 :: Int -> ByteString
    encode_u8 = Word8 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode (Word8 -> ByteString) -> (Int -> Word8) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Word8
    int_to_word8

    -- | Type specialised 'Binary.encode'.
    --
    -- > encode_w16 0x0102 == L.pack [1,2]
    encode_w16 :: Word16 -> L.ByteString
    encode_w16 :: Word16 -> ByteString
    encode_w16 = Word16 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode

    -- | Little-endian.
    --
    -- > encode_w16_le 0x0102 == L.pack [2,1]
    encode_w16_le :: Word16 -> L.ByteString
    encode_w16_le :: Word16 -> ByteString
    encode_w16_le = Put -> ByteString
    Put.runPut (Put -> ByteString) -> (Word16 -> Put) -> Word16 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word16 -> Put
    Put.putWord16le

    -- | Encode an un-signed 16-bit integer.
    --
    -- > encode_u16 0x0102 == L.pack [1,2]
    encode_u16 :: Int -> L.ByteString
    encode_u16 :: Int -> ByteString
    encode_u16 = Word16 -> ByteString
    encode_w16 (Word16 -> ByteString) -> (Int -> Word16) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Word16
    int_to_word16

    -- | Little-endian.
    --
    -- > encode_u16_le 0x0102 == L.pack [2,1]
    encode_u16_le :: Int -> L.ByteString
    encode_u16_le :: Int -> ByteString
    encode_u16_le = Word16 -> ByteString
    encode_w16_le (Word16 -> ByteString) -> (Int -> Word16) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Word16
    int_to_word16

    -- | Encode a signed 16-bit integer.
    encode_i16 :: Int -> L.ByteString
    encode_i16 :: Int -> ByteString
    encode_i16 = Int16 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode (Int16 -> ByteString) -> (Int -> Int16) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Int16
    int_to_int16

    -- | Encode a signed 32-bit integer.
    encode_i32 :: Int -> L.ByteString
    encode_i32 :: Int -> ByteString
    encode_i32 = Int32 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode (Int32 -> ByteString) -> (Int -> Int32) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Int32
    int_to_int32

    -- | Type specialised 'Binary.encode'.
    encode_w32 :: Word32 -> L.ByteString
    encode_w32 :: Word32 -> ByteString
    encode_w32 = Word32 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode

    -- | Encode an unsigned 32-bit integer.
    --
    -- > encode_u32 0x01020304 == L.pack [1,2,3,4]
    encode_u32 :: Int -> L.ByteString
    encode_u32 :: Int -> ByteString
    encode_u32 = Word32 -> ByteString
    encode_w32 (Word32 -> ByteString) -> (Int -> Word32) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Word32
    int_to_word32

    -- | Little-endian variant of 'encode_w32'.
    encode_w32_le :: Word32 -> L.ByteString
    encode_w32_le :: Word32 -> ByteString
    encode_w32_le = Put -> ByteString
    Put.runPut (Put -> ByteString) -> (Word32 -> Put) -> Word32 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word32 -> Put
    Put.putWord32le

    -- | Little-endian.
    --
    -- > encode_u32_le 0x01020304 == L.pack [4,3,2,1]
    encode_u32_le :: Int -> L.ByteString
    encode_u32_le :: Int -> ByteString
    encode_u32_le = Word32 -> ByteString
    encode_w32_le (Word32 -> ByteString) -> (Int -> Word32) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Word32
    int_to_word32

    -- | Encode a signed 64-bit integer.
    encode_i64 :: Int64 -> L.ByteString
    encode_i64 :: Int64 -> ByteString
    encode_i64 = Int64 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode

    -- | Encode an unsigned 64-bit integer.
    encode_u64 :: Word64 -> L.ByteString
    encode_u64 :: Word64 -> ByteString
    encode_u64 = Word64 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode

    -- | Encode a 32-bit IEEE floating point number.
    encode_f32 :: Float -> L.ByteString
    encode_f32 :: Float -> ByteString
    encode_f32 = Word32 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode (Word32 -> ByteString) -> (Float -> Word32) -> Float -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Float -> Word32
    Cast.f32_w32

    -- | Little-endian variant of 'encode_f32'.
    encode_f32_le :: Float -> L.ByteString
    encode_f32_le :: Float -> ByteString
    encode_f32_le = Put -> ByteString
    Put.runPut (Put -> ByteString) -> (Float -> Put) -> Float -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word32 -> Put
    Put.putWord32le (Word32 -> Put) -> (Float -> Word32) -> Float -> Put
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Float -> Word32
    Cast.f32_w32

    -- | Encode a 64-bit IEEE floating point number.
    encode_f64 :: Double -> L.ByteString
    encode_f64 :: Double -> ByteString
    encode_f64 = Word64 -> ByteString
    forall a. Binary a => a -> ByteString
    Binary.encode (Word64 -> ByteString)
    -> (Double -> Word64) -> Double -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Double -> Word64
    Cast.f64_w64

    -- | Encode an ASCII string (ASCII at Datum is an alias for a Char8 Bytetring).
    encode_str :: S.C.ByteString -> L.ByteString
    {-# INLINE encode_str #-}
    encode_str :: ByteString -> ByteString
    encode_str = [Word8] -> ByteString
    L.pack ([Word8] -> ByteString)
    -> (ByteString -> [Word8]) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> [Word8]
    S.unpack

    -- * Decode

    -- | Decode an un-signed 8-bit integer.
    decode_u8 :: L.ByteString -> Int
    decode_u8 :: ByteString -> Int
    decode_u8 = Word8 -> Int
    word8_to_int (Word8 -> Int) -> (ByteString -> Word8) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word8
    L.head

    -- | Decode a signed 8-bit integer.
    decode_i8 :: L.ByteString -> Int
    decode_i8 :: ByteString -> Int
    decode_i8 = Int8 -> Int
    int8_to_int (Int8 -> Int) -> (ByteString -> Int8) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Int8
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Type specialised 'Binary.decode'.
    decode_word16 :: L.ByteString -> Word16
    decode_word16 :: ByteString -> Word16
    decode_word16 = ByteString -> Word16
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Decode an unsigned 8-bit integer.
    decode_u16 :: L.ByteString -> Int
    decode_u16 :: ByteString -> Int
    decode_u16 = Word16 -> Int
    word16_to_int (Word16 -> Int) -> (ByteString -> Word16) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word16
    decode_word16

    -- | Little-endian variant of 'decode_word16'.
    decode_word16_le :: L.ByteString -> Word16
    decode_word16_le :: ByteString -> Word16
    decode_word16_le = Get Word16 -> ByteString -> Word16
    forall a. Get a -> ByteString -> a
    Get.runGet Get Word16
    Get.getWord16le

    -- | Little-endian variant of 'decode_u16'.
    decode_u16_le :: L.ByteString -> Int
    decode_u16_le :: ByteString -> Int
    decode_u16_le = Word16 -> Int
    word16_to_int (Word16 -> Int) -> (ByteString -> Word16) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word16
    decode_word16_le

    -- | Type specialised 'Binary.decode'.
    decode_int16 :: L.ByteString -> Int16
    decode_int16 :: ByteString -> Int16
    decode_int16 = ByteString -> Int16
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Decode a signed 16-bit integer.
    decode_i16 :: L.ByteString -> Int
    decode_i16 :: ByteString -> Int
    decode_i16 = Int16 -> Int
    int16_to_int (Int16 -> Int) -> (ByteString -> Int16) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Int16
    decode_int16

    -- | Little-endian variant of 'decode_i16'.
    decode_i16_le :: L.ByteString -> Int
    decode_i16_le :: ByteString -> Int
    decode_i16_le = ByteString -> Int
    decode_i16 (ByteString -> Int)
    -> (ByteString -> ByteString) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ByteString
    L.reverse

    -- | Decode a signed 32-bit integer.
    decode_i32 :: L.ByteString -> Int
    decode_i32 :: ByteString -> Int
    decode_i32 = Int32 -> Int
    int32_to_int (Int32 -> Int) -> (ByteString -> Int32) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Int32
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Type specialised 'Binary.decode'.
    decode_word32 :: L.ByteString -> Word32
    decode_word32 :: ByteString -> Word32
    decode_word32 = ByteString -> Word32
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Decode an unsigned 32-bit integer.
    --
    -- > decode_u32 (L.pack [1,2,3,4]) == 0x01020304
    decode_u32 :: L.ByteString -> Int
    decode_u32 :: ByteString -> Int
    decode_u32 = Word32 -> Int
    word32_to_int (Word32 -> Int) -> (ByteString -> Word32) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word32
    decode_word32

    -- | Little-endian variant of 'decode_word32'.
    decode_word32_le :: L.ByteString -> Word32
    decode_word32_le :: ByteString -> Word32
    decode_word32_le = Get Word32 -> ByteString -> Word32
    forall a. Get a -> ByteString -> a
    Get.runGet Get Word32
    Get.getWord32le

    -- | Little-endian variant of decode_u32.
    --
    -- > decode_u32_le (L.pack [1,2,3,4]) == 0x04030201
    decode_u32_le :: L.ByteString -> Int
    decode_u32_le :: ByteString -> Int
    decode_u32_le = Word32 -> Int
    word32_to_int (Word32 -> Int) -> (ByteString -> Word32) -> ByteString -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word32
    decode_word32_le

    -- | Type specialised 'Binary.decode'.
    decode_i64 :: L.ByteString -> Int64
    decode_i64 :: ByteString -> Int64
    decode_i64 = ByteString -> Int64
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Type specialised 'Binary.decode'.
    decode_u64 :: L.ByteString -> Word64
    decode_u64 :: ByteString -> Word64
    decode_u64 = ByteString -> Word64
    forall a. Binary a => ByteString -> a
    Binary.decode

    -- | Decode a 32-bit IEEE floating point number.
    decode_f32 :: L.ByteString -> Float
    decode_f32 :: ByteString -> Float
    decode_f32 = Word32 -> Float
    Cast.w32_f32 (Word32 -> Float) -> (ByteString -> Word32) -> ByteString -> Float
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word32
    decode_word32

    -- | Little-endian variant of 'decode_f32'.
    decode_f32_le :: L.ByteString -> Float
    decode_f32_le :: ByteString -> Float
    decode_f32_le = Word32 -> Float
    Cast.w32_f32 (Word32 -> Float) -> (ByteString -> Word32) -> ByteString -> Float
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Word32
    decode_word32_le

    -- | Decode a 64-bit IEEE floating point number.
    decode_f64 :: L.ByteString -> Double
    decode_f64 :: ByteString -> Double
    decode_f64 b :: ByteString
    b = Word64 -> Double
    Cast.w64_f64 (ByteString -> Word64
    forall a. Binary a => ByteString -> a
    Binary.decode ByteString
    b :: Word64)

    -- | Decode an ASCII string, inverse of 'encode_str'.
    decode_str :: L.ByteString -> S.C.ByteString
    {-# INLINE decode_str #-}
    decode_str :: ByteString -> ByteString
    decode_str = String -> ByteString
    S.C.pack (String -> ByteString)
    -> (ByteString -> String) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> String
    L.C.unpack

    -- * IO

    -- | 'decode_i8' of 'L.hGet'.
    read_i8 :: Handle -> IO Int
    read_i8 :: Handle -> IO Int
    read_i8 = (ByteString -> Int) -> IO ByteString -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Int
    decode_i8 (IO ByteString -> IO Int)
    -> (Handle -> IO ByteString) -> Handle -> IO Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    L.hGet 1

    -- | 'decode_i16' of 'L.hGet'.
    read_i16 :: Handle -> IO Int
    read_i16 :: Handle -> IO Int
    read_i16 = (ByteString -> Int) -> IO ByteString -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Int
    decode_i16 (IO ByteString -> IO Int)
    -> (Handle -> IO ByteString) -> Handle -> IO Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    L.hGet 2

    -- | 'decode_i32' of 'L.hGet'.
    read_i32 :: Handle -> IO Int
    read_i32 :: Handle -> IO Int
    read_i32 = (ByteString -> Int) -> IO ByteString -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Int
    decode_i32 (IO ByteString -> IO Int)
    -> (Handle -> IO ByteString) -> Handle -> IO Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    L.hGet 4

    -- | 'decode_u32' of 'L.hGet'.
    read_u32 :: Handle -> IO Int
    read_u32 :: Handle -> IO Int
    read_u32 = (ByteString -> Int) -> IO ByteString -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Int
    decode_u32 (IO ByteString -> IO Int)
    -> (Handle -> IO ByteString) -> Handle -> IO Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    L.hGet 4

    -- | 'decode_u32_le' of 'L.hGet'.
    read_u32_le :: Handle -> IO Int
    read_u32_le :: Handle -> IO Int
    read_u32_le = (ByteString -> Int) -> IO ByteString -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Int
    decode_u32_le (IO ByteString -> IO Int)
    -> (Handle -> IO ByteString) -> Handle -> IO Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    L.hGet 4

    -- | 'decode_f32' of 'L.hGet'.
    read_f32 :: Handle -> IO Float
    read_f32 :: Handle -> IO Float
    read_f32 = (ByteString -> Float) -> IO ByteString -> IO Float
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Float
    decode_f32 (IO ByteString -> IO Float)
    -> (Handle -> IO ByteString) -> Handle -> IO Float
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Handle -> Int -> IO ByteString) -> Int -> Handle -> IO ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Handle -> Int -> IO ByteString
    L.hGet 4

    -- | Read u8 length prefixed ASCII string (pascal string).
    read_pstr :: Handle -> IO S.C.ByteString
    read_pstr :: Handle -> IO ByteString
    read_pstr h :: Handle
    h = do
      Int
    n <- (ByteString -> Int) -> IO ByteString -> IO Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Int
    decode_u8 (Handle -> Int -> IO ByteString
    L.hGet Handle
    h 1)
      (ByteString -> ByteString) -> IO ByteString -> IO ByteString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> ByteString
    decode_str (Handle -> Int -> IO ByteString
    L.hGet Handle
    h Int
    n)

    -- | 'L.hPut' of 'encode_u32'.
    write_u32 :: Handle -> Int -> IO ()
    write_u32 :: Handle -> Int -> IO ()
    write_u32 h :: Handle
    h = Handle -> ByteString -> IO ()
    L.hPut Handle
    h (ByteString -> IO ()) -> (Int -> ByteString) -> Int -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> ByteString
    encode_u32

    -- | 'L.hPut' of 'encode_u32_le'.
    write_u32_le :: Handle -> Int -> IO ()
    write_u32_le :: Handle -> Int -> IO ()
    write_u32_le h :: Handle
    h = Handle -> ByteString -> IO ()
    L.hPut Handle
    h (ByteString -> IO ()) -> (Int -> ByteString) -> Int -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> ByteString
    encode_u32_le

    -- | Bundle header as a (strict) 'S.C.ByteString'.
    bundleHeader_strict :: S.C.ByteString
    bundleHeader_strict :: ByteString
    bundleHeader_strict = String -> ByteString
    S.C.pack "#bundle\0"

    -- | Bundle header as a lazy ByteString.
    bundleHeader :: L.ByteString
    {-# INLINE bundleHeader #-}
    bundleHeader :: ByteString
    bundleHeader = [ByteString] -> ByteString
    L.C.fromChunks [ByteString
    bundleHeader_strict]

    -- | The number of bytes required to align an OSC value to the next
    --   4-byte boundary.
    --
    -- > map align [0::Int .. 7] == [0,3,2,1,0,3,2,1]
    align :: (Num i,Bits i) => i -> i
    {-# INLINE align #-}
    align :: i -> i
    align n :: i
    n = ((i
    n i -> i -> i
    forall a. Num a => a -> a -> a
    + 3) i -> i -> i
    forall a. Bits a => a -> a -> a
    .&. i -> i
    forall a. Bits a => a -> a
    complement 3) i -> i -> i
    forall a. Num a => a -> a -> a
    - i
    n