{-# OPTIONS_GHC -fno-warn-orphans #-} module Codec.Bytable.BigEndian () where import Data.Bits import Data.Word import Data.Word.Word24 import Codec.Bytable import qualified Data.ByteString as BS instance Bytable Int where decode bs | BS.length bs <= 4 = Right $ byteStringToNum bs | otherwise = Left "Codec.Bytable.BigEndian: Bytable Int: too large" encode = integralToByteStringN 4 instance Bytable Integer where decode bs = Right $ byteStringToNum bs encode = integralToByteString instance Bytable Word16 where decode bs | BS.length bs <= 2 = Right $ byteStringToNum bs | otherwise = Left "Codec.Bytable.BigEndian: Bytable Word16: too large" encode = integralToByteStringN 2 instance Bytable Word24 where decode bs | BS.length bs <= 3 = Right $ byteStringToNum bs | otherwise = Left "Codec.Bytable.BigEndian: Bytable Word24: too large" encode = integralToByteStringN 3 instance Bytable Word32 where decode bs | BS.length bs <= 4 = Right $ byteStringToNum bs | otherwise = Left "Codec.Bytable.BigEndian: Bytable Word32: too large" encode = integralToByteStringN 4 instance Bytable Word64 where decode bs | BS.length bs <= 8 = Right $ byteStringToNum bs | otherwise = Left "Codec.Bytable.BigEndian: Bytable Word32: too large" encode = integralToByteStringN 8 byteStringToNum :: (Num n, Bits n) => BS.ByteString -> n byteStringToNum = wordsToNum . reverse . BS.unpack wordsToNum :: (Num n, Bits n) => [Word8] -> n wordsToNum [] = 0 wordsToNum (w : ws) = fromIntegral w .|. wordsToNum ws `shiftL` 8 integralToByteString :: (Integral n, Bits n) => n -> BS.ByteString integralToByteString = BS.pack . reverse . integralToWords integralToByteStringN :: (Integral n, Bits n) => Int -> n -> BS.ByteString integralToByteStringN n = BS.pack . (\ws -> replicate (n - length ws) 0 ++ ws) . reverse . integralToWords integralToWords :: (Integral n, Bits n) => n -> [Word8] integralToWords 0 = [] integralToWords n = fromIntegral n : integralToWords (n `shiftR` 8)