2
votes

Is there some ready-made function that converts Word32 and Word64 between big/little/host-endian representations? As pointed out in the comments, this shouldn't be needed if (de)serialization is performed correctly, but could be handy in some specific situations when dealing with low-level code.

I found the following solutions, neither perfect:

  1. Use byteorder to determine the current host order, and if little-endian, use byteSwap32 on each word (or alternatively the one from base-compat.

    case byteOrder of
        LittleEndian -> byteSwap32
        _ -> id
    
  2. Serialize the words with cereal's putWord32be and immediately read them with getWord32host (or alternativly putWord32host and read with getWord32be). This adds somewhat more heavy-weight dependency, but gives more flexibility for conversions to other formats.

    either (error "Unexpected error when converting ip address") id
    . runGet getWord32host . runPut . putWord32be
    
  3. Import the native functions:

    foreign import ccall unsafe "htonl" htonl :: Word32 -> Word32
    foreign import ccall unsafe "ntohl" ntohl :: Word32 -> Word32
    

Is there anything better or more convenient?

1
Found this old Cafe thread: (link) Unfortunately the thread doesn't say what happened to the functions. - ErikR
It is unclear what goal you are trying to achieve. Host byte order is usually what you want. The byte order only starts to matter as soon as you look at individual bytes ... which you typically do when you serialize the address. Then, a serialization library such as cereal would be the way to go.*Only exception:* You use memcpy or pass the value to foreign functions. Then use the native functions (htonl and co). - sapanoia
@sapanoia You're right. Misled by the comment, II thought that HostAddress6 stores data in its Word32 in such a way that programs can observe the difference depending on the architecture. After examining the source code, parsing struct in6_addr is actually not host dependent. So for using network this shouldn't be needed at all. While my question still applies, in correct scenarios where (de)serialization is done correctly, it shouldn't be needed. - Petr

1 Answers

3
votes

Yes, there are in System.Endian module within cpu package. I also needed it for my purposes. It has many utility functions for that like:

getSystemEndianness :: Endianness

gets the current CPU endianess

fromLE64 :: Word64 -> Word64

from LE64 to platform endianess

fromBE64 :: Word64 -> Word64

same as above but from BE 64

toLE64 :: Word64 -> Word64

from CPU's Endianess to LE64

toBE64 :: Word64 -> Word64

from CPU's Endianess to BE64

Please note that the module provides same functions for Word32 and Word16: https://hackage.haskell.org/package/cpu-0.1.2/docs/System-Endian.html