-- |
-- Utils for dealing with integer numbers.
module PostgreSQL.Binary.Integral where

import qualified Data.ByteString as B
import PostgreSQL.Binary.Prelude

{-# INLINEABLE pack #-}
pack :: (Bits a, Num a) => B.ByteString -> a
pack :: forall a. (Bits a, Num a) => ByteString -> a
pack =
  (a -> Word8 -> a) -> a -> ByteString -> a
forall a. (a -> Word8 -> a) -> a -> ByteString -> a
B.foldl' (\a
n Word8
h -> a -> Int -> a
forall a. Bits a => a -> Int -> a
shiftL a
n Int
8 a -> a -> a
forall a. Bits a => a -> a -> a
.|. Word8 -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
h) a
0

{-# INLINE unpackBySize #-}
unpackBySize :: (Bits a, Integral a) => Int -> a -> B.ByteString
unpackBySize :: forall a. (Bits a, Integral a) => Int -> a -> ByteString
unpackBySize Int
n a
x =
  [Word8] -> ByteString
B.pack ([Word8] -> ByteString) -> [Word8] -> ByteString
forall a b. (a -> b) -> a -> b
$ (Int -> Word8) -> [Int] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Word8
f ([Int] -> [Word8]) -> [Int] -> [Word8]
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int]
forall a. [a] -> [a]
reverse [Int
0 .. Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
  where
    f :: Int -> Word8
f Int
s =
      a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> Word8) -> a -> Word8
forall a b. (a -> b) -> a -> b
$ a -> Int -> a
forall a. Bits a => a -> Int -> a
shiftR a
x (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
s)