byte-order-0.1.3.1: Portable big-endian and little-endian conversions

Safe Haskell | None
Language | Haskell2010

System.ByteOrder

Contents

- Types
- Classes
- Conversion
- System Byte Order
- Example

Description

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:

- Untyped Conversions: The functions `toBigEndian`, `toLittleEndian`, `fromBigEndian`, and `fromLittleEndian` convert between native-endian words and big/little-endian words. The word resulting from `to(Big|Little)Endian` should be written to a primitive byte array or a pointer afterwards. (There is no other purpose of such a conversion.) Similarly, the argument to `from(Big|Little)Endian` should be a word that was read from a primitive byte array or a pointer. This interface is useful when serializing or deserializing a data structure with fields of varying sizes.
- Typed Conversions: The type `Fixed` provides a convenient type-directed interface to working with arrays of homogenous words. This interface is easier to use and should be preferred when possible.

The example at the bottom of this page demonstrates how to use the type-directed interface.

Synopsis

- data ByteOrder
  - = BigEndian
  - | LittleEndian
- newtype Fixed (a :: ByteOrder) b where
  - Fixed :: forall (a :: ByteOrder) b. {..} -> Fixed a b
- class Bytes a
- class FixedOrdering (b :: ByteOrder)
- toBigEndian :: Bytes a => a -> a
- toLittleEndian :: Bytes a => a -> a
- fromBigEndian :: Bytes a => a -> a
- fromLittleEndian :: Bytes a => a -> a
- targetByteOrder :: ByteOrder

# Types

data ByteOrder Source #

Byte ordering.

Constructors

BigEndian | most-significant-byte occurs in lowest address.
LittleEndian | least-significant-byte occurs in lowest address.

#### Instances

Instances details

Bounded ByteOrder | Since: base-4.11.0.0
Instance details Defined in GHC.Internal.ByteOrder Methods minBound :: ByteOrder Source # maxBound :: ByteOrder Source #
Enum ByteOrder | Since: base-4.11.0.0

Instance details

Defined in GHC.Internal.ByteOrder

Methods

succ :: ByteOrder -> ByteOrder Source #

pred :: ByteOrder -> ByteOrder Source #

toEnum :: Int -> ByteOrder Source #

fromEnum :: ByteOrder -> Int Source #

enumFrom :: ByteOrder -> [ByteOrder] Source #

enumFromThen :: ByteOrder -> ByteOrder -> [ByteOrder] Source #

enumFromTo :: ByteOrder -> ByteOrder -> [ByteOrder] Source #

enumFromThenTo :: ByteOrder -> ByteOrder -> ByteOrder -> [ByteOrder] Source #

Generic ByteOrder |

Instance details

Defined in GHC.Internal.ByteOrder

Associated Types

type Rep ByteOrder | Since: base-4.15.0.0
Instance details Defined in GHC.Internal.ByteOrder type Rep ByteOrder = D1 ('MetaData "ByteOrder" "GHC.Internal.ByteOrder" "ghc-internal" 'False) (C1 ('MetaCons "BigEndian" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "LittleEndian" 'PrefixI 'False) (U1 :: Type -> Type))

Methods

from :: ByteOrder -> Rep ByteOrder x Source #

to :: Rep ByteOrder x -> ByteOrder Source #

Read ByteOrder | Since: base-4.11.0.0
Instance details Defined in GHC.Internal.ByteOrder Methods readsPrec :: Int -> ReadS ByteOrder Source # readList :: ReadS [ByteOrder] Source # readPrec :: ReadPrec ByteOrder Source # readListPrec :: ReadPrec [ByteOrder] Source #
Show ByteOrder | Since: base-4.11.0.0
Instance details Defined in GHC.Internal.ByteOrder Methods showsPrec :: Int -> ByteOrder -> ShowS Source # show :: ByteOrder -> String Source # showList :: [ByteOrder] -> ShowS Source #
Eq ByteOrder | Since: base-4.11.0.0
Instance details Defined in GHC.Internal.ByteOrder Methods (==) :: ByteOrder -> ByteOrder -> Bool Source # (/=) :: ByteOrder -> ByteOrder -> Bool Source #
Ord ByteOrder | Since: base-4.11.0.0

Instance details

Defined in GHC.Internal.ByteOrder

Methods

compare :: ByteOrder -> ByteOrder -> Ordering Source #

(<) :: ByteOrder -> ByteOrder -> Bool Source #

(<=) :: ByteOrder -> ByteOrder -> Bool Source #

(>) :: ByteOrder -> ByteOrder -> Bool Source #

(>=) :: ByteOrder -> ByteOrder -> Bool Source #

max :: ByteOrder -> ByteOrder -> ByteOrder Source #

min :: ByteOrder -> ByteOrder -> ByteOrder Source #

type Rep ByteOrder | Since: base-4.15.0.0
Instance details Defined in GHC.Internal.ByteOrder type Rep ByteOrder = D1 ('MetaData "ByteOrder" "GHC.Internal.ByteOrder" "ghc-internal" 'False) (C1 ('MetaCons "BigEndian" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "LittleEndian" 'PrefixI 'False) (U1 :: Type -> Type))

newtype Fixed (a :: ByteOrder) b where Source #

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

Constructors

Fixed |

Fields

- :: forall (a :: ByteOrder) b. { getFixed :: b
- } -> Fixed a b

#### Instances

Instances details

Enum a => Enum (Fixed b a) Source # |

Instance details

Defined in System.ByteOrder

Methods

succ :: Fixed b a -> Fixed b a Source #

pred :: Fixed b a -> Fixed b a Source #

toEnum :: Int -> Fixed b a Source #

fromEnum :: Fixed b a -> Int Source #

enumFrom :: Fixed b a -> [Fixed b a] Source #

enumFromThen :: Fixed b a -> Fixed b a -> [Fixed b a] Source #

enumFromTo :: Fixed b a -> Fixed b a -> [Fixed b a] Source #

enumFromThenTo :: Fixed b a -> Fixed b a -> Fixed b a -> [Fixed b a] Source #

(FixedOrdering b, Storable a, Bytes a) => Storable (Fixed b a) Source # |

Instance details

Defined in System.ByteOrder

Methods

sizeOf :: Fixed b a -> Int Source #

alignment :: Fixed b a -> Int Source #

peekElemOff :: Ptr (Fixed b a) -> Int -> IO (Fixed b a) Source #

pokeElemOff :: Ptr (Fixed b a) -> Int -> Fixed b a -> IO () Source #

peekByteOff :: Ptr b0 -> Int -> IO (Fixed b a) Source #

pokeByteOff :: Ptr b0 -> Int -> Fixed b a -> IO () Source #

peek :: Ptr (Fixed b a) -> IO (Fixed b a) Source #

poke :: Ptr (Fixed b a) -> Fixed b a -> IO () Source #

Num a => Num (Fixed b a) Source # |
Instance details Defined in System.ByteOrder Methods (+) :: Fixed b a -> Fixed b a -> Fixed b a Source # (-) :: Fixed b a -> Fixed b a -> Fixed b a Source # (*) :: Fixed b a -> Fixed b a -> Fixed b a Source # negate :: Fixed b a -> Fixed b a Source # abs :: Fixed b a -> Fixed b a Source # signum :: Fixed b a -> Fixed b a Source # fromInteger :: Integer -> Fixed b a Source #
Integral a => Integral (Fixed b a) Source # |

Instance details

Defined in System.ByteOrder

Methods

quot :: Fixed b a -> Fixed b a -> Fixed b a Source #

rem :: Fixed b a -> Fixed b a -> Fixed b a Source #

div :: Fixed b a -> Fixed b a -> Fixed b a Source #

mod :: Fixed b a -> Fixed b a -> Fixed b a Source #

quotRem :: Fixed b a -> Fixed b a -> (Fixed b a, Fixed b a) Source #

divMod :: Fixed b a -> Fixed b a -> (Fixed b a, Fixed b a) Source #

toInteger :: Fixed b a -> Integer Source #

Real a => Real (Fixed b a) Source # |
Instance details Defined in System.ByteOrder Methods toRational :: Fixed b a -> Rational Source #
Eq a => Eq (Fixed b a) Source # |
Instance details Defined in System.ByteOrder Methods (==) :: Fixed b a -> Fixed b a -> Bool Source # (/=) :: Fixed b a -> Fixed b a -> Bool Source #
Ord a => Ord (Fixed b a) Source # |

Instance details

Defined in System.ByteOrder

Methods

compare :: Fixed b a -> Fixed b a -> Ordering Source #

(<) :: Fixed b a -> Fixed b a -> Bool Source #

(<=) :: Fixed b a -> Fixed b a -> Bool Source #

(>) :: Fixed b a -> Fixed b a -> Bool Source #

(>=) :: Fixed b a -> Fixed b a -> Bool Source #

max :: Fixed b a -> Fixed b a -> Fixed b a Source #

min :: Fixed b a -> Fixed b a -> Fixed b a Source #

(FixedOrdering b, Prim a, Bytes a) => Prim (Fixed b a) Source # |

Instance details

Defined in System.ByteOrder

Methods

sizeOfType# :: Proxy (Fixed b a) -> Int# Source #

sizeOf# :: Fixed b a -> Int# Source #

alignmentOfType# :: Proxy (Fixed b a) -> Int# Source #

alignment# :: Fixed b a -> Int# Source #

indexByteArray# :: ByteArray# -> Int# -> Fixed b a Source #

readByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Fixed b a #) Source #

writeByteArray# :: MutableByteArray# s -> Int# -> Fixed b a -> State# s -> State# s Source #

setByteArray# :: MutableByteArray# s -> Int# -> Int# -> Fixed b a -> State# s -> State# s Source #

indexOffAddr# :: Addr# -> Int# -> Fixed b a Source #

readOffAddr# :: Addr# -> Int# -> State# s -> (# State# s, Fixed b a #) Source #

writeOffAddr# :: Addr# -> Int# -> Fixed b a -> State# s -> State# s Source #

setOffAddr# :: Addr# -> Int# -> Int# -> Fixed b a -> State# s -> State# s Source #

(FixedOrdering b, PrimUnaligned a, Bytes a) => PrimUnaligned (Fixed b a) Source # |
Instance details Defined in System.ByteOrder Methods indexUnalignedByteArray# :: ByteArray# -> Int# -> Fixed b a Source # readUnalignedByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, Fixed b a #) Source # writeUnalignedByteArray# :: MutableByteArray# s -> Int# -> Fixed b a -> State# s -> State# s Source #

# Classes

class Bytes a Source #

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.

Minimal complete definition

toBigEndian, toLittleEndian

#### Instances

Instances details

Bytes Int16 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Int16 -> Int16 Source # toLittleEndian :: Int16 -> Int16 Source #
Bytes Int32 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Int32 -> Int32 Source # toLittleEndian :: Int32 -> Int32 Source #
Bytes Int64 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Int64 -> Int64 Source # toLittleEndian :: Int64 -> Int64 Source #
Bytes Int8 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Int8 -> Int8 Source # toLittleEndian :: Int8 -> Int8 Source #
Bytes Word16 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word16 -> Word16 Source # toLittleEndian :: Word16 -> Word16 Source #
Bytes Word32 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word32 -> Word32 Source # toLittleEndian :: Word32 -> Word32 Source #
Bytes Word64 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word64 -> Word64 Source # toLittleEndian :: Word64 -> Word64 Source #
Bytes Word8 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word8 -> Word8 Source # toLittleEndian :: Word8 -> Word8 Source #
Bytes Word128 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word128 -> Word128 Source # toLittleEndian :: Word128 -> Word128 Source #
Bytes Word256 Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word256 -> Word256 Source # toLittleEndian :: Word256 -> Word256 Source #
Bytes Word Source # |
Instance details Defined in System.ByteOrder.Class Methods toBigEndian :: Word -> Word Source # toLittleEndian :: Word -> Word Source #

class FixedOrdering (b :: ByteOrder) Source #

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`.

Minimal complete definition

toFixedEndian

#### Instances

Instances details

FixedOrdering 'BigEndian Source # |
Instance details Defined in System.ByteOrder.Class Methods toFixedEndian :: Bytes a => a -> a Source #
FixedOrdering 'LittleEndian Source # |
Instance details Defined in System.ByteOrder.Class Methods toFixedEndian :: Bytes a => a -> a Source #

# Conversion

toBigEndian :: Bytes a => a -> a Source #

Convert from a native-endian word to a big-endian word.

toLittleEndian :: Bytes a => a -> a Source #

Convert from a native-endian word to a little-endian word.

fromBigEndian :: Bytes a => a -> a Source #

Convert from a big-endian word to a native-endian word.

fromLittleEndian :: Bytes a => a -> a Source #

Convert from a little-endian word to a native-endian word.

# System Byte Order

targetByteOrder :: ByteOrder Source #

The byte ordering of the target machine.

# Example

Suppose there is a protocol for aggregating numbers that uses stream sockets for communication. The protocol interprets all numbers as unsigned. It is described as follows:

1. The client sends the server a little-endian 16-bit number `N`. This is how many numbers will follow.
2. The client sends `N` little-endian 64-bit numbers to the server.
3. The server responds with two little-endian 64-bit numbers: the sum and the product of the `N` numbers it received.

Assume the existence of a `send` and `receive` that block until the total number of requested bytes have been handled. They both work on their argument arrays starting at index zero, which ensures that any 2-byte, 4-byte, or 8-byte types will be aligned properly. (GHC always machine-word aligns the payload of a byte array.) Additionally, assume the `typed` and `untyped` functions that convert between `PrimArray` and `ByteArray` by changing out the data constructor.

    send :: Socket -> ByteArray -> IO ()
    receive :: Socket -> Int -> IO ByteArray
    typed :: ByteArray -> PrimArray a
    untyped :: PrimArray a -> ByteArray

For simplicity, all error-handling is omitted. With the type-directed interface, the server is implemented as:

    import Data.Primitive.ByteArray
    import Data.Primitive.PrimArray
    import System.ByteOrder

    server :: Socket -> IO a
    server sckt = forever $ do
      totalByteArray <- receive sckt 2
      let totalPrimArray = typed totalByteArray :: PrimArray (Fixed 'LittleEndian Word16)
      let Fixed total = indexPrimArray totalPrimArray 0
      numberByteArray <- receive sckt (8 * fromIntegral @Word16 @Int total)
      let (sum,prod) = foldlPrimArray'
            (\(!sumN,!prodN) (Fixed n) -> (sumN + n, prodN * n))
            (0,1)
            (typed numberByteArray :: PrimArray (Fixed 'LittleEndian Word64))
      reply :: MutablePrimArray RealWorld (Fixed 'LittleEndian Word64) <- newPrimArray 2
      writePrimArray reply 0 (Fixed sum)
      writePrimArray reply 1 (Fixed prod)
      send sckt . untyped =<< unsafeFreezePrimArray reply

Not every explicit type annotation above is needed. Some are provided 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.