byte-order 0.1.3.0 → 0.1.3.1
raw patch · 9 files changed
+297/−238 lines, 9 filessetup-changednew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- System.ByteOrder: [Fixed] :: forall (b :: ByteOrder) (a :: Type). {getFixed :: a} -> Fixed b a
+ System.ByteOrder: [Fixed] :: forall (b :: ByteOrder) (a :: Type). a -> Fixed b a
- System.ByteOrder: data ByteOrder
+ System.ByteOrder: data () => ByteOrder
Files
- CHANGELOG.md +4/−0
- Setup.hs +0/−2
- byte-order.cabal +32/−24
- src/Data/Primitive/ByteArray/BigEndian.hs +50/−32
- src/Data/Primitive/ByteArray/LittleEndian.hs +61/−36
- src/Data/Primitive/Ptr/BigEndian.hs +19/−15
- src/System/ByteOrder.hs +59/−56
- src/System/ByteOrder/Class.hs +68/−67
- test/Unit.hs +4/−6
CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for byte-order +## 0.1.3.1 -- 2024-02-01++* Update package metadata.+ ## 0.1.3.0 -- 2021-02-22 * Add a module for big-endian access to pointers.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
byte-order.cabal view
@@ -1,46 +1,54 @@-cabal-version: 2.2-name: byte-order-version: 0.1.3.0-synopsis: Portable big-endian and little-endian conversions+cabal-version: 2.2+name: byte-order+version: 0.1.3.1+synopsis: Portable big-endian and little-endian conversions description: This library provides an interface to portably work with byte arrays whose contents are known to be of a fixed endianness. There are two ways to use this module. See the `System.ByteOrder` module for more documentation.-homepage: https://github.com/andrewthad/byte-order-bug-reports: https://github.com/andrewthad/byte-order/issues-license: BSD-3-Clause-license-file: LICENSE-author: Andrew Martin-maintainer: andrew.thaddeus@gmail.com-copyright: 2019 Andrew Martin-category: Data-extra-source-files: CHANGELOG.md +homepage: https://github.com/byteverse/byte-order+bug-reports: https://github.com/byteverse/byte-order/issues+license: BSD-3-Clause+license-file: LICENSE+author: Andrew Martin+maintainer: amartin@layer3com.com+copyright: 2019 Andrew Martin+category: Data+extra-doc-files: CHANGELOG.md+ library exposed-modules:- Data.Primitive.Ptr.BigEndian Data.Primitive.ByteArray.BigEndian Data.Primitive.ByteArray.LittleEndian+ Data.Primitive.Ptr.BigEndian System.ByteOrder System.ByteOrder.Class+ build-depends:- , 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+ , base >=4.11.1.0 && <5+ , primitive >=0.6.4 && <0.10+ , 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+ ghc-options: -O2 -Wall test-suite unit- type: exitcode-stdio-1.0- hs-source-dirs: test- main-is: Unit.hs+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Unit.hs build-depends: , base , byte-order , primitive , wide-word- ghc-options: -Wall -O2++ ghc-options: -Wall -O2 default-language: Haskell2010++source-repository head+ type: git+ location: git://github.com/byteverse/byte-order.git
src/Data/Primitive/ByteArray/BigEndian.hs view
@@ -1,60 +1,78 @@--- | This is drop-in replacement for the read, write, and index functions--- present in @Data.Primitive.ByteArray@ and @Data.Primitive.ByteArray.Unaligned@.--- While the functions from those modules use native byte order, the functions--- in this one use big-endian byte order (most significant byte first).+{- | This is drop-in replacement for the read, write, and index functions+present in @Data.Primitive.ByteArray@ and @Data.Primitive.ByteArray.Unaligned@.+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.ByteArray.BigEndian ( -- * Aligned writeByteArray , readByteArray , indexByteArray+ -- * Unaligned , writeUnalignedByteArray , readUnalignedByteArray , indexUnalignedByteArray ) where -import Data.Primitive (Prim,MutableByteArray,ByteArray)-import Control.Monad.Primitive (PrimState,PrimMonad)-import System.ByteOrder (Bytes,toBigEndian,fromBigEndian)-import Data.Primitive.ByteArray.Unaligned (PrimUnaligned)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Primitive (ByteArray, MutableByteArray, Prim) import qualified Data.Primitive as PM+import Data.Primitive.ByteArray.Unaligned (PrimUnaligned) import qualified Data.Primitive.ByteArray.Unaligned as PMU+import System.ByteOrder (Bytes, fromBigEndian, toBigEndian) --- | Write a primitive value to the byte array. The offset is given--- in elements of type @a@ rather than in bytes. The most significant--- byte in the value comes first.+{- | Write a primitive value to the byte array. The offset is given+in elements of type @a@ rather than in bytes. The most significant+byte in the value comes first.+-} writeByteArray :: (PrimMonad m, Prim a, Bytes a) => MutableByteArray (PrimState m) -> Int -> a -> m () writeByteArray arr ix v = PM.writeByteArray arr ix (toBigEndian v) --- | Read a primitive value from the byte array, interpreting the first--- byte as the most significant one. The offset is given in elements of--- type @a@ rather than in bytes.+{- | Read a primitive value from the byte array, interpreting the first+byte as the most significant one. The offset is given in elements of+type @a@ rather than in bytes.+-} readByteArray :: (PrimMonad m, Prim a, Bytes a) => MutableByteArray (PrimState m) -> Int -> m a readByteArray arr ix = fromBigEndian <$> PM.readByteArray arr ix --- | Read a primitive value from the byte array, interpreting the first--- byte as the most significant one. The offset is given in elements of--- type @a@ rather than in bytes.+{- | Read a primitive value from the byte array, interpreting the first+byte as the most significant one. The offset is given in elements of+type @a@ rather than in bytes.+-} indexByteArray :: (Prim a, Bytes a) => ByteArray -> Int -> a indexByteArray arr ix = fromBigEndian (PM.indexByteArray arr ix) --- | Write a primitive value to the byte array. The offset is given--- in bytes rather than in elements of type @a@. The most significant--- byte in the value comes first.-writeUnalignedByteArray :: (PrimMonad m, PrimUnaligned a, Bytes a)- => MutableByteArray (PrimState m) -> Int -> a -> m ()+{- | Write a primitive value to the byte array. The offset is given+in bytes rather than in elements of type @a@. The most significant+byte in the value comes first.+-}+writeUnalignedByteArray ::+ (PrimMonad m, PrimUnaligned a, Bytes a) =>+ MutableByteArray (PrimState m) ->+ Int ->+ a ->+ m () writeUnalignedByteArray arr ix v = PMU.writeUnalignedByteArray arr ix (toBigEndian v) --- | Read a primitive value from the byte array, interpreting the first--- byte as the most significant one. The offset is given in bytes rather--- than in elements of type @a@.-readUnalignedByteArray :: (PrimMonad m, PrimUnaligned a, Bytes a)- => MutableByteArray (PrimState m) -> Int -> m a+{- | Read a primitive value from the byte array, interpreting the first+byte as the most significant one. The offset is given in bytes rather+than in elements of type @a@.+-}+readUnalignedByteArray ::+ (PrimMonad m, PrimUnaligned a, Bytes a) =>+ MutableByteArray (PrimState m) ->+ Int ->+ m a readUnalignedByteArray arr ix = fromBigEndian <$> PMU.readUnalignedByteArray arr ix --- | Read a primitive value from the byte array, interpreting the first--- byte as the most significant one. The offset is given in bytes rather--- than in elements of type @a@.-indexUnalignedByteArray :: (PrimUnaligned a, Bytes a)- => ByteArray -> Int -> a+{- | Read a primitive value from the byte array, interpreting the first+byte as the most significant one. The offset is given in bytes rather+than in elements of type @a@.+-}+indexUnalignedByteArray ::+ (PrimUnaligned a, Bytes a) =>+ ByteArray ->+ Int ->+ a indexUnalignedByteArray arr ix = fromBigEndian (PMU.indexUnalignedByteArray arr ix)
src/Data/Primitive/ByteArray/LittleEndian.hs view
@@ -1,62 +1,87 @@--- | This is drop-in replacement for the read, write, and index functions--- present in @Data.Primitive.ByteArray@ and @Data.Primitive.ByteArray.Unaligned@.--- While the functions from those modules use native byte order, the functions--- in this one use little-endian byte order (least significant byte first).+{- | This is drop-in replacement for the read, write, and index functions+present in @Data.Primitive.ByteArray@ and @Data.Primitive.ByteArray.Unaligned@.+While the functions from those modules use native byte order, the functions+in this one use little-endian byte order (least significant byte first).+-} module Data.Primitive.ByteArray.LittleEndian ( -- * Aligned writeByteArray , readByteArray , indexByteArray+ -- * Unaligned , writeUnalignedByteArray , readUnalignedByteArray , indexUnalignedByteArray ) where -import Data.Primitive (Prim,MutableByteArray,ByteArray)-import Control.Monad.Primitive (PrimState,PrimMonad)-import System.ByteOrder (Bytes,toLittleEndian,fromLittleEndian)-import Data.Primitive.ByteArray.Unaligned (PrimUnaligned)+import Control.Monad.Primitive (PrimMonad, PrimState)+import Data.Primitive (ByteArray, MutableByteArray, Prim) import qualified Data.Primitive as PM+import Data.Primitive.ByteArray.Unaligned (PrimUnaligned) import qualified Data.Primitive.ByteArray.Unaligned as PMU+import System.ByteOrder (Bytes, fromLittleEndian, toLittleEndian) --- | Write a primitive value to the byte array. The offset is given--- in elements of type @a@ rather than in bytes. The least significant--- byte in the value comes first.-writeByteArray :: (PrimMonad m, Prim a, Bytes a)- => MutableByteArray (PrimState m) -> Int -> a -> m ()+{- | Write a primitive value to the byte array. The offset is given+in elements of type @a@ rather than in bytes. The least significant+byte in the value comes first.+-}+writeByteArray ::+ (PrimMonad m, Prim a, Bytes a) =>+ MutableByteArray (PrimState m) ->+ Int ->+ a ->+ m () writeByteArray arr ix v = PM.writeByteArray arr ix (toLittleEndian v) --- | Read a primitive value from the byte array, interpreting the first--- byte as the least significant one. The offset is given in elements of--- type @a@ rather than in bytes.-readByteArray :: (PrimMonad m, Prim a, Bytes a)- => MutableByteArray (PrimState m) -> Int -> m a+{- | Read a primitive value from the byte array, interpreting the first+byte as the least significant one. The offset is given in elements of+type @a@ rather than in bytes.+-}+readByteArray ::+ (PrimMonad m, Prim a, Bytes a) =>+ MutableByteArray (PrimState m) ->+ Int ->+ m a readByteArray arr ix = fromLittleEndian <$> PM.readByteArray arr ix --- | Read a primitive value from the byte array, interpreting the first--- byte as the least significant one. The offset is given in elements of--- type @a@ rather than in bytes.+{- | Read a primitive value from the byte array, interpreting the first+byte as the least significant one. The offset is given in elements of+type @a@ rather than in bytes.+-} indexByteArray :: (Prim a, Bytes a) => ByteArray -> Int -> a indexByteArray arr ix = fromLittleEndian (PM.indexByteArray arr ix) --- | Write a primitive value to the byte array. The offset is given--- in bytes rather than in elements of type @a@. The least significant--- byte in the value comes first.-writeUnalignedByteArray :: (PrimMonad m, PrimUnaligned a, Bytes a)- => MutableByteArray (PrimState m) -> Int -> a -> m ()+{- | Write a primitive value to the byte array. The offset is given+in bytes rather than in elements of type @a@. The least significant+byte in the value comes first.+-}+writeUnalignedByteArray ::+ (PrimMonad m, PrimUnaligned a, Bytes a) =>+ MutableByteArray (PrimState m) ->+ Int ->+ a ->+ m () writeUnalignedByteArray arr ix v = PMU.writeUnalignedByteArray arr ix (toLittleEndian v) --- | Read a primitive value from the byte array, interpreting the first--- byte as the least significant one. The offset is given in bytes rather--- than in elements of type @a@.-readUnalignedByteArray :: (PrimMonad m, PrimUnaligned a, Bytes a)- => MutableByteArray (PrimState m) -> Int -> m a+{- | Read a primitive value from the byte array, interpreting the first+byte as the least significant one. The offset is given in bytes rather+than in elements of type @a@.+-}+readUnalignedByteArray ::+ (PrimMonad m, PrimUnaligned a, Bytes a) =>+ MutableByteArray (PrimState m) ->+ Int ->+ m a readUnalignedByteArray arr ix = fromLittleEndian <$> PMU.readUnalignedByteArray arr ix --- | Read a primitive value from the byte array, interpreting the first--- byte as the least significant one. The offset is given in bytes rather--- than in elements of type @a@.-indexUnalignedByteArray :: (PrimUnaligned a, Bytes a)- => ByteArray -> Int -> a+{- | Read a primitive value from the byte array, interpreting the first+byte as the least significant one. The offset is given in bytes rather+than in elements of type @a@.+-}+indexUnalignedByteArray ::+ (PrimUnaligned a, Bytes a) =>+ ByteArray ->+ Int ->+ a indexUnalignedByteArray arr ix = fromLittleEndian (PMU.indexUnalignedByteArray arr ix)
src/Data/Primitive/Ptr/BigEndian.hs view
@@ -1,7 +1,8 @@--- | 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).+{- | 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@@ -9,26 +10,29 @@ , indexOffPtr ) where +import Control.Monad.Primitive (PrimMonad) 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+import System.ByteOrder (Bytes, fromBigEndian, toBigEndian) --- | 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.+{- | 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.+{- | 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.+{- | 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.hs view
@@ -1,16 +1,16 @@-{-# language DataKinds #-}-{-# language DerivingStrategies #-}-{-# language GeneralizedNewtypeDeriving #-}-{-# language GADTSyntax #-}-{-# language KindSignatures #-}-{-# language MagicHash #-}-{-# language RoleAnnotations #-}-{-# language ScopedTypeVariables #-}-{-# language StandaloneDeriving #-}-{-# language TypeApplications #-}-{-# language UnboxedTuples #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GADTSyntax #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE UnboxedTuples #-} -{-| This module offers an interface to portably work with byte+{- | This module offers an interface to portably work with byte arrays whose contents are known to be of a fixed endianness. There are two ways to use this module: @@ -31,21 +31,24 @@ The example at the bottom of this page demonstrates how to use the type-directed interface. -}- module System.ByteOrder ( -- * Types- ByteOrder(..)- , Fixed(..)+ ByteOrder (..)+ , Fixed (..)+ -- * Classes , Bytes , FixedOrdering+ -- * Conversion , toBigEndian , toLittleEndian , fromBigEndian , fromLittleEndian+ -- * System Byte Order , targetByteOrder+ -- * Example -- $example ) where@@ -53,50 +56,51 @@ import Data.Kind (Type) import Data.Primitive.ByteArray.Unaligned (PrimUnaligned) import Data.Primitive.Types (Prim)-import Foreign.Ptr (Ptr,castPtr)+import Foreign.Ptr (Ptr, castPtr) import Foreign.Storable (Storable)-import GHC.ByteOrder (ByteOrder(..),targetByteOrder)-import System.ByteOrder.Class (Bytes(..),FixedOrdering,toFixedEndian)+import GHC.ByteOrder (ByteOrder (..), targetByteOrder)+import System.ByteOrder.Class (Bytes (..), FixedOrdering, toFixedEndian) -import qualified Data.Primitive.Types as PM import qualified Data.Primitive.ByteArray.Unaligned as PMU+import qualified Data.Primitive.Types as PM import qualified Foreign.Storable as FS -- | Convert from a big-endian word to a native-endian word.-fromBigEndian :: Bytes a => a -> a+fromBigEndian :: (Bytes a) => a -> a fromBigEndian = toBigEndian -- | Convert from a little-endian word to a native-endian word.-fromLittleEndian :: Bytes a => a -> a+fromLittleEndian :: (Bytes a) => a -> a fromLittleEndian = toLittleEndian --- | A word whose byte order is specified (not platform dependent)--- when working with 'Prim', 'Storable', and @PrimUnaligned@ (this--- last instance is provided alongside the typeclass itself in the--- @primitive-unaligned@ library).+{- | A word whose byte order is specified (not platform dependent)+when working with 'Prim', 'Storable', and @PrimUnaligned@ (this+last instance is provided alongside the typeclass itself in the+@primitive-unaligned@ library).+-} newtype Fixed :: ByteOrder -> Type -> Type where- Fixed :: forall (b :: ByteOrder) (a :: Type). { getFixed :: a } -> Fixed b a+ Fixed :: forall (b :: ByteOrder) (a :: Type). {getFixed :: a} -> Fixed b a type role Fixed phantom representational -deriving newtype instance Num a => Num (Fixed b a)-deriving newtype instance Real a => Real (Fixed b a)-deriving newtype instance Integral a => Integral (Fixed b a)-deriving newtype instance Ord a => Ord (Fixed b a)-deriving newtype instance Enum a => Enum (Fixed b a)-deriving newtype instance Eq a => Eq (Fixed b a)+deriving newtype instance (Num a) => Num (Fixed b a)+deriving newtype instance (Real a) => Real (Fixed b a)+deriving newtype instance (Integral a) => Integral (Fixed b a)+deriving newtype instance (Ord a) => Ord (Fixed b a)+deriving newtype instance (Enum a) => Enum (Fixed b a)+deriving newtype instance (Eq a) => Eq (Fixed b a) instance (FixedOrdering b, Prim a, Bytes a) => Prim (Fixed b a) where- {-# inline sizeOf# #-}- {-# inline alignment# #-}- {-# inline indexByteArray# #-}- {-# inline readByteArray# #-}- {-# inline writeByteArray# #-}- {-# inline setByteArray# #-}- {-# inline indexOffAddr# #-}- {-# inline readOffAddr# #-}- {-# inline writeOffAddr# #-}- {-# inline setOffAddr# #-}+ {-# INLINE sizeOf# #-}+ {-# INLINE alignment# #-}+ {-# INLINE indexByteArray# #-}+ {-# INLINE readByteArray# #-}+ {-# INLINE writeByteArray# #-}+ {-# INLINE setByteArray# #-}+ {-# INLINE indexOffAddr# #-}+ {-# INLINE readOffAddr# #-}+ {-# INLINE writeOffAddr# #-}+ {-# INLINE setOffAddr# #-} sizeOf# _ = PM.sizeOf# (undefined :: a) alignment# _ = PM.alignment# (undefined :: a) indexByteArray# a i = Fixed (toFixedEndian @b (PM.indexByteArray# a i))@@ -111,23 +115,23 @@ setOffAddr# a i n (Fixed x) = PM.setOffAddr# a i n (toFixedEndian @b x) instance (FixedOrdering b, PrimUnaligned a, Bytes a) => PrimUnaligned (Fixed b a) where- {-# inline indexUnalignedByteArray# #-}- {-# inline readUnalignedByteArray# #-}- {-# inline writeUnalignedByteArray# #-}+ {-# INLINE indexUnalignedByteArray# #-}+ {-# INLINE readUnalignedByteArray# #-}+ {-# INLINE writeUnalignedByteArray# #-} indexUnalignedByteArray# a i = Fixed (toFixedEndian @b (PMU.indexUnalignedByteArray# a i)) readUnalignedByteArray# a i s0 = case PMU.readUnalignedByteArray# a i s0 of (# s1, x #) -> (# s1, Fixed (toFixedEndian @b x) #) writeUnalignedByteArray# a i (Fixed x) = PMU.writeUnalignedByteArray# a i (toFixedEndian @b x) instance (FixedOrdering b, Storable a, Bytes a) => Storable (Fixed b a) where- {-# inline sizeOf #-}- {-# inline alignment #-}- {-# inline peekElemOff #-}- {-# inline pokeElemOff #-}- {-# inline peekByteOff #-}- {-# inline pokeByteOff #-}- {-# inline peek #-}- {-# inline poke #-}+ {-# INLINE sizeOf #-}+ {-# INLINE alignment #-}+ {-# INLINE peekElemOff #-}+ {-# INLINE pokeElemOff #-}+ {-# INLINE peekByteOff #-}+ {-# INLINE pokeByteOff #-}+ {-# INLINE peek #-}+ {-# INLINE poke #-} sizeOf _ = FS.sizeOf (undefined :: a) alignment _ = FS.alignment (undefined :: a) peekElemOff p i = fmap (Fixed . toFixedEndian @b) (FS.peekElemOff (fromFixedPtr p) i)@@ -138,7 +142,7 @@ poke p (Fixed x) = FS.poke (fromFixedPtr p) (toFixedEndian @b x) fromFixedPtr :: Ptr (Fixed b a) -> Ptr a-{-# inline fromFixedPtr #-}+{-# INLINE fromFixedPtr #-} fromFixedPtr = castPtr {- $example@@ -171,7 +175,7 @@ > import Data.Primitive.ByteArray > import Data.Primitive.PrimArray > import System.ByteOrder-> +> > server :: Socket -> IO a > server sckt = forever $ do > totalByteArray <- receive sckt 2@@ -191,5 +195,4 @@ for the reader's benefit. As long as the user ensures that the typed primitive arrays use 'Fixed' in their element types, the endianness conversions are guaranteed to be correct.- -}
src/System/ByteOrder/Class.hs view
@@ -1,46 +1,46 @@-{-# language AllowAmbiguousTypes #-}-{-# language DataKinds #-}-{-# language GADTSyntax #-}-{-# language KindSignatures #-}-{-# language MagicHash #-}-{-# language RoleAnnotations #-}-{-# language ScopedTypeVariables #-}-{-# language TypeApplications #-}-{-# language UnboxedTuples #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTSyntax #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RoleAnnotations #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} module System.ByteOrder.Class- ( FixedOrdering(..)- , Bytes(..)+ ( FixedOrdering (..)+ , Bytes (..) ) where -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#))+import Data.Int (Int16, Int32, Int64, Int8)+import Data.WideWord (Word128 (Word128), Word256 (Word256))+import Data.Word (Word16, Word32, Word64, Word8, byteSwap16, byteSwap32, byteSwap64)+import GHC.ByteOrder (ByteOrder (BigEndian, LittleEndian), targetByteOrder)+import GHC.Word (Word (W#)) import qualified GHC.Exts as Exts --- | Types that are represented as a fixed-sized word. For these--- types, the bytes can be swapped. The instances of this class--- use byteswapping primitives and compile-time knowledge of native--- endianness to provide portable endianness conversion functions.+{- | Types that are represented as a fixed-sized word. For these+types, the bytes can be swapped. The instances of this class+use byteswapping primitives and compile-time knowledge of native+endianness to provide portable endianness conversion functions.+-} class Bytes a where -- | Convert from a native-endian word to a big-endian word. toBigEndian :: a -> a+ -- | Convert from a native-endian word to a little-endian word. toLittleEndian :: a -> a instance Bytes Word8 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = id toLittleEndian = id instance Bytes Word16 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian -> byteSwap16@@ -49,8 +49,8 @@ LittleEndian -> id instance Bytes Word32 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian -> byteSwap32@@ -59,8 +59,8 @@ LittleEndian -> id instance Bytes Word64 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian -> byteSwap64@@ -69,8 +69,8 @@ LittleEndian -> id instance Bytes Word128 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian -> (\(Word128 hi lo) -> Word128 (byteSwap64 lo) (byteSwap64 hi))@@ -79,8 +79,8 @@ LittleEndian -> id instance Bytes Word256 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# 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))@@ -89,8 +89,8 @@ LittleEndian -> id instance Bytes Word where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian -> byteSwap@@ -99,65 +99,66 @@ LittleEndian -> id instance Bytes Int8 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = id toLittleEndian = id instance Bytes Int16 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian ->- fromIntegral @Word16 @Int16- . byteSwap16- . fromIntegral @Int16 @Word16+ fromIntegral @Word16 @Int16+ . byteSwap16+ . fromIntegral @Int16 @Word16 toLittleEndian = case targetByteOrder of BigEndian ->- fromIntegral @Word16 @Int16- . byteSwap16- . fromIntegral @Int16 @Word16+ fromIntegral @Word16 @Int16+ . byteSwap16+ . fromIntegral @Int16 @Word16 LittleEndian -> id instance Bytes Int32 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian ->- fromIntegral @Word32 @Int32- . byteSwap32- . fromIntegral @Int32 @Word32+ fromIntegral @Word32 @Int32+ . byteSwap32+ . fromIntegral @Int32 @Word32 toLittleEndian = case targetByteOrder of BigEndian ->- fromIntegral @Word32 @Int32- . byteSwap32- . fromIntegral @Int32 @Word32+ fromIntegral @Word32 @Int32+ . byteSwap32+ . fromIntegral @Int32 @Word32 LittleEndian -> id instance Bytes Int64 where- {-# inline toBigEndian #-}- {-# inline toLittleEndian #-}+ {-# INLINE toBigEndian #-}+ {-# INLINE toLittleEndian #-} toBigEndian = case targetByteOrder of BigEndian -> id LittleEndian ->- fromIntegral @Word64 @Int64- . byteSwap64- . fromIntegral @Int64 @Word64+ fromIntegral @Word64 @Int64+ . byteSwap64+ . fromIntegral @Int64 @Word64 toLittleEndian = case targetByteOrder of BigEndian ->- fromIntegral @Word64 @Int64- . byteSwap64- . fromIntegral @Int64 @Word64+ fromIntegral @Word64 @Int64+ . byteSwap64+ . fromIntegral @Int64 @Word64 LittleEndian -> id --- | A byte order that can be interpreted as a conversion function.--- This class is effectively closed. The only instances are for--- 'BigEndian' and 'LittleEndian'. It is not possible to write more--- instances since there are no other inhabitants of 'ByteOrder'.+{- | A byte order that can be interpreted as a conversion function.+This class is effectively closed. The only instances are for+'BigEndian' and 'LittleEndian'. It is not possible to write more+instances since there are no other inhabitants of 'ByteOrder'.+-} class FixedOrdering (b :: ByteOrder) where- toFixedEndian :: Bytes a => a -> a+ toFixedEndian :: (Bytes a) => a -> a instance FixedOrdering 'LittleEndian where toFixedEndian = toLittleEndian@@ -166,5 +167,5 @@ toFixedEndian = toBigEndian byteSwap :: Word -> Word-{-# inline byteSwap #-}+{-# INLINE byteSwap #-} byteSwap (W# w) = W# (Exts.byteSwap# w)
test/Unit.hs view
@@ -1,14 +1,13 @@-{-# language BangPatterns #-}-{-# language DataKinds #-}-{-# language ScopedTypeVariables #-}-{-# language TypeApplications #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} import Control.Monad (when) import Data.Primitive.ByteArray+import Data.WideWord (Word128) import Data.Word import GHC.Exts (RealWorld) import System.ByteOrder-import Data.WideWord (Word128) import qualified Data.Primitive.ByteArray.BigEndian as BE @@ -125,4 +124,3 @@ if v == w then pure () else fail (name ++ ": byte " ++ show ix ++ " was wrong, expected " ++ show w ++ " but got " ++ show v)-