@@ -38,6 +38,7 @@ import qualified Data.Vector.Unboxed.Base as VU
38
38
import Foreign.ForeignPtr ( ForeignPtr , withForeignPtr )
39
39
import Foreign.Ptr ( Ptr , castPtr )
40
40
import Foreign.Storable ( Storable (.. ) )
41
+ import GHC.ByteOrder ( ByteOrder (.. ), targetByteOrder )
41
42
import RIO hiding ( words )
42
43
import System.IO.Unsafe ( unsafePerformIO )
43
44
@@ -79,27 +80,31 @@ class DynamicBytes dbytes where
79
80
lengthD :: dbytes -> Int
80
81
-- Yeah, it looks terrible to use a list here, but fusion should kick in
81
82
withPeekD :: dbytes -> ((Int -> IO Word64 ) -> IO a ) -> IO a
83
+ -- ^ This assumes that the Word64 values are all little-endian.
82
84
-- | May throw a runtime exception if invariants are violated!
83
85
fromWordsD :: Int -> [Word64 ] -> dbytes
86
+ -- ^ This assumes that the Word64 values are all little-endian.
84
87
85
88
fromWordsForeign ::
86
89
(ForeignPtr a -> Int -> b )
87
90
-> Int
88
91
-> [Word64 ]
92
+ -- ^ The Word64 values are assumed to be little-endian.
89
93
-> b
90
94
fromWordsForeign wrapper len words0 = unsafePerformIO $ do
91
95
fptr <- B. mallocByteString len
92
96
withForeignPtr fptr $ \ ptr -> do
93
97
let loop _ [] = pure ()
94
98
loop off (w: ws) = do
95
- pokeElemOff (castPtr ptr) off w
99
+ pokeElemOff (castPtr ptr) off (fromLE64 w)
96
100
loop (off + 1 ) ws
97
101
loop 0 words0
98
102
pure $ wrapper fptr len
99
103
100
104
withPeekForeign ::
101
105
(ForeignPtr a , Int , Int )
102
106
-> ((Int -> IO Word64 ) -> IO b )
107
+ -- ^ The Word64 values are assumed to be little-endian.
103
108
-> IO b
104
109
withPeekForeign (fptr, off, len) inner =
105
110
withForeignPtr fptr $ \ ptr -> do
@@ -113,7 +118,7 @@ withPeekForeign (fptr, off, len) inner =
113
118
let w64' = shiftL (fromIntegral w8) (i * 8 ) .|. w64
114
119
loop w64' (i + 1 )
115
120
loop 0 0
116
- | otherwise = peekByteOff ptr (off + off')
121
+ | otherwise = toLE64 <$> peekByteOff ptr (off + off')
117
122
inner f
118
123
119
124
instance DynamicBytes B. ByteString where
@@ -133,7 +138,7 @@ instance word8 ~ Word8 => DynamicBytes (VP.Vector word8) where
133
138
let loop _ [] =
134
139
VP. Vector 0 len <$> BA. unsafeFreezeByteArray ba
135
140
loop i (w: ws) = do
136
- BA. writeByteArray ba i w
141
+ BA. writeByteArray ba i (fromLE64 w)
137
142
loop (i + 1 ) ws
138
143
loop 0 words0
139
144
withPeekD (VP. Vector off len ba) inner = do
@@ -147,7 +152,8 @@ instance word8 ~ Word8 => DynamicBytes (VP.Vector word8) where
147
152
let w64' = shiftL (fromIntegral w8) (i * 8 ) .|. w64
148
153
loop w64' (i + 1 )
149
154
loop 0 0
150
- | otherwise = pure $ BA. indexByteArray ba (off + (off' `div` 8 ))
155
+ | otherwise = pure $
156
+ toLE64 $ BA. indexByteArray ba (off + (off' `div` 8 ))
151
157
inner f
152
158
153
159
instance word8 ~ Word8 => DynamicBytes (VU. Vector word8 ) where
@@ -248,3 +254,13 @@ fromStatic ::
248
254
=> sbytes
249
255
-> dbytes
250
256
fromStatic = fromWordsD (lengthS (Nothing :: Maybe sbytes )) . ($ [] ) . toWordsS
257
+
258
+ -- | Convert a 64 bit value in CPU endianess to little endian.
259
+ toLE64 :: Word64 -> Word64
260
+ toLE64 = case targetByteOrder of
261
+ BigEndian -> byteSwap64
262
+ LittleEndian -> id
263
+
264
+ -- | Convert a little endian 64 bit value to CPU endianess.
265
+ fromLE64 :: Word64 -> Word64
266
+ fromLE64 = toLE64
0 commit comments