byte-order 0.1.2.0 → 0.1.3.0
raw patch · 5 files changed
+116/−8 lines, 5 filesdep +wide-worddep ~primitivePVP ok
version bump matches the API change (PVP)
Dependencies added: wide-word
Dependency ranges changed: primitive
API changes (from Hackage documentation)
+ Data.Primitive.Ptr.BigEndian: indexOffPtr :: (Prim a, Bytes a) => Ptr a -> Int -> a
+ Data.Primitive.Ptr.BigEndian: readOffPtr :: (PrimMonad m, Prim a, Bytes a) => Ptr a -> Int -> m a
+ Data.Primitive.Ptr.BigEndian: writeOffPtr :: (PrimMonad m, Prim a, Bytes a) => Ptr a -> Int -> a -> m ()
+ System.ByteOrder.Class: instance System.ByteOrder.Class.Bytes Data.WideWord.Word128.Word128
+ System.ByteOrder.Class: instance System.ByteOrder.Class.Bytes Data.WideWord.Word256.Word256
Files
- CHANGELOG.md +5/−0
- byte-order.cabal +4/−1
- src/Data/Primitive/Ptr/BigEndian.hs +34/−0
- src/System/ByteOrder/Class.hs +21/−0
- test/Unit.hs +52/−7
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for byte-order +## 0.1.3.0 -- 2021-02-22++* Add a module for big-endian access to pointers.+* Add `Bytes` instances for `Word128` and `Word256`.+ ## 0.1.2.0 -- 2020-01-06 * Add a `Bytes` instance for `Word`.
byte-order.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: byte-order-version: 0.1.2.0+version: 0.1.3.0 synopsis: Portable big-endian and little-endian conversions description: This library provides an interface to portably work with byte@@ -19,6 +19,7 @@ library exposed-modules:+ Data.Primitive.Ptr.BigEndian Data.Primitive.ByteArray.BigEndian Data.Primitive.ByteArray.LittleEndian System.ByteOrder@@ -27,6 +28,7 @@ , base >=4.11.1.0 && <5 , primitive >=0.6.4 && <0.8 , primitive-unaligned >=0.1.1 && <0.2+ , wide-word >=0.1.1 && <0.2 hs-source-dirs: src default-language: Haskell2010 ghc-options: -O2 -Wall@@ -39,5 +41,6 @@ , base , byte-order , primitive+ , wide-word ghc-options: -Wall -O2 default-language: Haskell2010
+ src/Data/Primitive/Ptr/BigEndian.hs view
@@ -0,0 +1,34 @@+-- | This is drop-in replacement for the read, write, and index functions+-- present in @Data.Primitive.Ptr@. While the functions from those modules+-- use native byte order, the functions in this one use big-endian byte order+-- (most significant byte first).+module Data.Primitive.Ptr.BigEndian+ ( -- * Aligned+ writeOffPtr+ , readOffPtr+ , indexOffPtr+ ) where++import Data.Primitive (Prim)+import Data.Primitive.Ptr (Ptr)+import Control.Monad.Primitive (PrimMonad)+import System.ByteOrder (Bytes,toBigEndian,fromBigEndian)+import qualified Data.Primitive.Ptr as PM++-- | Write a primitive value to the pointer. The offset is given+-- in elements of type @a@ rather than in bytes. The most significant+-- byte in the value comes first.+writeOffPtr :: (PrimMonad m, Prim a, Bytes a) => Ptr a -> Int -> a -> m ()+writeOffPtr arr ix v = PM.writeOffPtr arr ix (toBigEndian v)++-- | Read a primitive value from the pointer, interpreting the first+-- byte as the most significant one. The offset is given in elements of+-- type @a@ rather than in bytes.+readOffPtr :: (PrimMonad m, Prim a, Bytes a) => Ptr a -> Int -> m a+readOffPtr arr ix = fromBigEndian <$> PM.readOffPtr arr ix++-- | Read a primitive value from the pointer, interpreting the first+-- byte as the most significant one. The offset is given in elements of+-- type @a@ rather than in bytes.+indexOffPtr :: (Prim a, Bytes a) => Ptr a -> Int -> a+indexOffPtr arr ix = fromBigEndian (PM.indexOffPtr arr ix)
src/System/ByteOrder/Class.hs view
@@ -16,6 +16,7 @@ import Data.Int (Int8,Int16,Int32,Int64) import Data.Word (Word8,Word16,Word32,Word64) import Data.Word (byteSwap16,byteSwap32,byteSwap64)+import Data.WideWord (Word128(Word128),Word256(Word256)) import GHC.ByteOrder (ByteOrder(BigEndian,LittleEndian),targetByteOrder) import GHC.Word (Word(W#)) @@ -65,6 +66,26 @@ LittleEndian -> byteSwap64 toLittleEndian = case targetByteOrder of BigEndian -> byteSwap64+ LittleEndian -> id++instance Bytes Word128 where+ {-# inline toBigEndian #-}+ {-# inline toLittleEndian #-}+ toBigEndian = case targetByteOrder of+ BigEndian -> id+ LittleEndian -> (\(Word128 hi lo) -> Word128 (byteSwap64 lo) (byteSwap64 hi))+ toLittleEndian = case targetByteOrder of+ BigEndian -> (\(Word128 hi lo) -> Word128 (byteSwap64 lo) (byteSwap64 hi))+ LittleEndian -> id++instance Bytes Word256 where+ {-# inline toBigEndian #-}+ {-# inline toLittleEndian #-}+ toBigEndian = case targetByteOrder of+ BigEndian -> id+ LittleEndian -> (\(Word256 a b c d) -> Word256 (byteSwap64 d) (byteSwap64 c) (byteSwap64 b) (byteSwap64 a))+ toLittleEndian = case targetByteOrder of+ BigEndian -> (\(Word256 a b c d) -> Word256 (byteSwap64 d) (byteSwap64 c) (byteSwap64 b) (byteSwap64 a)) LittleEndian -> id instance Bytes Word where
test/Unit.hs view
@@ -3,11 +3,15 @@ {-# language ScopedTypeVariables #-} {-# language TypeApplications #-} +import Control.Monad (when) import Data.Primitive.ByteArray import Data.Word import GHC.Exts (RealWorld) import System.ByteOrder+import Data.WideWord (Word128) +import qualified Data.Primitive.ByteArray.BigEndian as BE+ main :: IO () main = do putStrLn "Start"@@ -19,6 +23,10 @@ testC putStrLn "D" testD+ putStrLn "E"+ testE+ putStrLn "F"+ testF putStrLn "Finished" testA :: IO ()@@ -27,11 +35,10 @@ marr <- newByteArray 4 setByteArray marr 0 4 (0x00 :: Word8) writeByteArray marr 0 (Fixed @'LittleEndian payload)- let name = "testA"- expectByte name marr 0 0x67- expectByte name marr 1 0x45- expectByte name marr 2 0x23- expectByte name marr 3 0x01+ expectByte "testA, byte 0" marr 0 0x67+ expectByte "testA, byte 1" marr 1 0x45+ expectByte "testA, byte 2" marr 2 0x23+ expectByte "testA, byte 3" marr 3 0x01 testB :: IO () testB = do@@ -67,17 +74,55 @@ marr <- newByteArray 20 setByteArray marr 0 20 (0x00 :: Word8) writeByteArray marr 0 (Fixed @'LittleEndian payload)- let name = "testA"+ let name = "testD" expectByte name marr 0 0x67 expectByte name marr 1 0x45 expectByte name marr 2 0x23 expectByte name marr 3 0x01 expectByte name marr 4 0x00 +testE :: IO ()+testE = do+ marr <- newByteArray 8+ writeByteArray marr 0 (0xFF :: Word8)+ writeByteArray marr 1 (0xFF :: Word8)+ writeByteArray marr 2 (0xFF :: Word8)+ writeByteArray marr 3 (0xFF :: Word8)+ writeByteArray marr 4 (0x00 :: Word8)+ writeByteArray marr 5 (0x06 :: Word8)+ writeByteArray marr 6 (0x96 :: Word8)+ writeByteArray marr 7 (0x9c :: Word8)+ r <- BE.readByteArray marr 1+ let expected = 0x0006969c :: Word32+ when (r /= expected) (fail "testE failed")++testF :: IO ()+testF = do+ marr <- newByteArray 32+ writeByteArray marr 16 (0x00 :: Word8)+ writeByteArray marr 17 (0x01 :: Word8)+ writeByteArray marr 18 (0x02 :: Word8)+ writeByteArray marr 19 (0x03 :: Word8)+ writeByteArray marr 20 (0x04 :: Word8)+ writeByteArray marr 21 (0x05 :: Word8)+ writeByteArray marr 22 (0x06 :: Word8)+ writeByteArray marr 23 (0x07 :: Word8)+ writeByteArray marr 24 (0x08 :: Word8)+ writeByteArray marr 25 (0x09 :: Word8)+ writeByteArray marr 26 (0x0A :: Word8)+ writeByteArray marr 27 (0x0B :: Word8)+ writeByteArray marr 28 (0x0C :: Word8)+ writeByteArray marr 29 (0x0D :: Word8)+ writeByteArray marr 30 (0x0E :: Word8)+ writeByteArray marr 31 (0x0F :: Word8)+ r <- BE.readByteArray marr 1+ let expected = 0x000102030405060708090A0B0C0D0E0F :: Word128+ when (r /= expected) (fail "testF failed")+ expectByte :: String -> MutableByteArray RealWorld -> Int -> Word8 -> IO () expectByte name marr ix w = do v <- readByteArray marr ix if v == w then pure ()- else fail (name ++ ": byte " ++ show ix ++ " was wrong")+ else fail (name ++ ": byte " ++ show ix ++ " was wrong, expected " ++ show w ++ " but got " ++ show v)