File: big-endian

package info (click to toggle)
haskell-static-bytes 0.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 104 kB
  • sloc: haskell: 283; makefile: 3
file content (92 lines) | stat: -rw-r--r-- 3,694 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
From 08d19aaf328fd456960f689fa66e0bfb7eebf28b Mon Sep 17 00:00:00 2001
From: Mike Pilgrem <mpilgrem@users.noreply.github.com>
Date: Sun, 20 Oct 2024 20:29:04 +0100
Subject: [PATCH] Fix #1 Enforce that the Word64 values used are little-endian.

Index: b/src/Data/StaticBytes.hs
===================================================================
--- a/src/Data/StaticBytes.hs
+++ b/src/Data/StaticBytes.hs
@@ -34,6 +34,7 @@ import qualified Data.Vector.Unboxed.Bas
 import           Foreign.ForeignPtr
 import           Foreign.Ptr
 import           Foreign.Storable
+import           GHC.ByteOrder ( ByteOrder (..), targetByteOrder )
 import           RIO hiding ( words )
 import           System.IO.Unsafe ( unsafePerformIO )
 
@@ -75,20 +76,23 @@ class DynamicBytes dbytes where
   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 +100,7 @@ fromWordsForeign wrapper len words0 = un
 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 +114,7 @@ withPeekForeign (fptr, off, len) inner =
                         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 +134,7 @@ instance word8 ~ Word8 => DynamicBytes (
     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 +148,8 @@ instance word8 ~ Word8 => DynamicBytes (
                         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 +250,13 @@ fromStatic ::
   => 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