pairing-0.4.1: src/Pairing/ByteRepr.hs
module Pairing.ByteRepr (
ByteRepr(..),
toBytes,
toPaddedBytes,
fromBytesToInteger,
ByteOrder(..),
ByteOrderLength(..)
) where
import Protolude
import Data.ByteString as B
data ByteOrder = MostSignificantFirst | LeastSignificantFirst
type ElementLength = Int
data ByteOrderLength = ByteOrderLength { byteOrder :: ByteOrder, lenPerElement :: ElementLength }
class ByteRepr a where
mkRepr :: ByteOrderLength -> a -> Maybe ByteString
fromRepr :: ByteOrderLength -> a -> ByteString -> Maybe a
calcReprLength :: a -> ElementLength -> Int
toBytes :: Integer -> ByteString
toBytes x = B.reverse . B.unfoldr (fmap go) . Just $ changeSign x
where
changeSign :: Num a => a -> a
changeSign | x < 0 = subtract 1 . negate
| otherwise = identity
go :: Integer -> (Word8, Maybe Integer)
go x = (b, i)
where
b = changeSign (fromInteger x)
i | x >= 128 = Just (x `shiftR` 8)
| otherwise = Nothing
toPaddedBytes :: ByteOrderLength -> Integer -> Maybe ByteString
toPaddedBytes bo a = case byteOrder bo of
LeastSignificantFirst -> B.reverse <$> mkbs (toBytes a)
MostSignificantFirst -> mkbs (toBytes a)
where
mkbs bs
| B.length bs > lenPerElement bo = Nothing
| B.length bs == lenPerElement bo = Just bs
| otherwise = Just (B.append (B.replicate (lenPerElement bo - B.length bs) 0x0) bs)
fromBytesToInteger :: ByteOrder -> ByteString -> Integer
fromBytesToInteger MostSignificantFirst = B.foldl' f 0
where
f a b = a `shiftL` 8 .|. fromIntegral b
fromBytesToInteger LeastSignificantFirst = (fromBytesToInteger MostSignificantFirst) . B.reverse