packages feed

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 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)