packages feed

static-bytes 0.1.0 → 0.1.1

raw patch · 3 files changed

+36/−11 lines, 3 files

Files

CHANGELOG.md view
@@ -6,6 +6,11 @@ and this project adheres to the
 [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
+## 0.1.1 - 2024-10-21
+
+* Ensure that the functionality on big-endian machine architectures is the same
+  as that on little-endian machine architectures. 
+
 ## 0.1.0 - 2023-07-07
 
 * Spin out module `Pantry.Internal.StaticBytes` from package `pantry-0.8.3`.
src/Data/StaticBytes.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE NoImplicitPrelude   #-}
+{-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DeriveAnyClass      #-}
 {-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE DeriveGeneric       #-}
@@ -22,18 +23,22 @@   , fromStatic
   ) where
 
-import           Data.Bits
-import           Data.ByteArray
+import           Data.Bits ( Bits (..) )
+import           Data.ByteArray ( ByteArrayAccess (..) )
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Internal as B
 import qualified Data.Primitive.ByteArray as BA
+#if MIN_VERSION_GLASGOW_HASKELL(9,4,1,0)
+import           Data.Type.Equality ( type (~) )
+#endif
 import qualified Data.Vector.Primitive as VP
 import qualified Data.Vector.Storable as VS
 import qualified Data.Vector.Unboxed as VU
 import qualified Data.Vector.Unboxed.Base as VU
-import           Foreign.ForeignPtr
-import           Foreign.Ptr
-import           Foreign.Storable
+import           Foreign.ForeignPtr ( ForeignPtr, withForeignPtr )
+import           Foreign.Ptr ( Ptr, castPtr )
+import           Foreign.Storable ( Storable (..) )
+import           GHC.ByteOrder ( ByteOrder (..), targetByteOrder )
 import           RIO hiding ( words )
 import           System.IO.Unsafe ( unsafePerformIO )
 
@@ -75,20 +80,23 @@   lengthD :: dbytes -> Int
   -- Yeah, it looks terrible to use a list here, but fusion should kick in
   withPeekD :: dbytes -> ((Int -> IO Word64) -> IO a) -> IO a
+  -- ^ This assumes that the Word64 values are all little-endian.
   -- | May throw a runtime exception if invariants are violated!
   fromWordsD :: Int -> [Word64] -> dbytes
+  -- ^ This assumes that the Word64 values are all little-endian.
 
 fromWordsForeign ::
      (ForeignPtr a -> Int -> b)
   -> Int
   -> [Word64]
+     -- ^ The Word64 values are assumed to be little-endian.
   -> b
 fromWordsForeign wrapper len words0 = unsafePerformIO $ do
   fptr <- B.mallocByteString len
   withForeignPtr fptr $ \ptr -> do
     let loop _ [] = pure ()
         loop off (w:ws) = do
-          pokeElemOff (castPtr ptr) off w
+          pokeElemOff (castPtr ptr) off (fromLE64 w)
           loop (off + 1) ws
     loop 0 words0
   pure $ wrapper fptr len
@@ -96,6 +104,7 @@ withPeekForeign ::
      (ForeignPtr a, Int, Int)
   -> ((Int -> IO Word64) -> IO b)
+     -- ^ The Word64 values are assumed to be little-endian.
   -> IO b
 withPeekForeign (fptr, off, len) inner =
   withForeignPtr fptr $ \ptr -> do
@@ -109,7 +118,7 @@                         let w64' = shiftL (fromIntegral w8) (i * 8) .|. w64
                         loop w64' (i + 1)
               loop 0 0
-          | otherwise = peekByteOff ptr (off + off')
+          | otherwise = toLE64 <$> peekByteOff ptr (off + off')
     inner f
 
 instance DynamicBytes B.ByteString where
@@ -129,7 +138,7 @@     let loop _ [] =
           VP.Vector 0 len <$> BA.unsafeFreezeByteArray ba
         loop i (w:ws) = do
-          BA.writeByteArray ba i w
+          BA.writeByteArray ba i (fromLE64 w)
           loop (i + 1) ws
     loop 0 words0
   withPeekD (VP.Vector off len ba) inner = do
@@ -143,7 +152,8 @@                         let w64' = shiftL (fromIntegral w8) (i * 8) .|. w64
                         loop w64' (i + 1)
               loop 0 0
-          | otherwise = pure $ BA.indexByteArray ba (off + (off' `div` 8))
+          | otherwise = pure $
+              toLE64 $ BA.indexByteArray ba (off + (off' `div` 8))
     inner f
 
 instance word8 ~ Word8 => DynamicBytes (VU.Vector word8) where
@@ -244,3 +254,13 @@   => sbytes
   -> dbytes
 fromStatic = fromWordsD (lengthS (Nothing :: Maybe sbytes)) . ($ []) . toWordsS
+
+-- | Convert a 64 bit value in CPU endianess to little endian.
+toLE64 :: Word64 -> Word64
+toLE64 = case targetByteOrder of
+  BigEndian -> byteSwap64
+  LittleEndian -> id
+
+-- | Convert a little endian 64 bit value to CPU endianess.
+fromLE64 :: Word64 -> Word64
+fromLE64 = toLE64
static-bytes.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12
 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack  name:           static-bytes-version:        0.1.0+version:        0.1.1 synopsis:       A Haskell library providing types representing 8, 16, 32, 64 or 128 bytes of data. description:    Please see the README on GitHub at <https://github.com/commercialhaskell/static-bytes#readme> category:       Data