[Haskell-cafe] Re: Data.Binary and little endian encoding

David Leimbach leimy2k at gmail.com
Thu May 28 12:35:44 EDT 2009

On Thu, May 28, 2009 at 9:17 AM, John Van Enk <vanenkj at gmail.com> wrote:

>> Fair enough.   I am just new to the interface, wondering if I should
>> try matching responses by pulling apart via Get, or the bit syntax
>> package.
> I'm assming you have some 'data Foo = ...'? If this is the case, you're
> probably okay writing an instance of Binary for Foo and using encode/decode.
> That's all I've had to do and had superb performance.

encode/decode do Big Endian, and 9P does little endian.

>From the man page:

"Each message consists of a sequence of bytes. Two–, four–, and eight–byte
fields hold unsigned integers represented in little–endian order (least
significant byte first)."

encode/decode just won't work for me as a result, as they assume the
not-so-aptly-named (at least in this case) "network" byte order.  Since I'm
not Rob Pike, or Ken Thompson or any of the Plan 9 guys, I can't tell you
why they chose little endian for this.

(I should note that I sometimes work with CAN hardware, and depending on
what people want to put on the line, little endian creeps in there too, so
this issue will have to be dealt with here as well, if I am to use

I've got (typing from memory, forgive syntax errors)

module Nine (Message) where

{-- missing imports --}

notag = putWord16le -1

-- Message type field values
-- from: http://plan9.bell-labs.com/sources/plan9/sys/include/fcall.h
tversion = 100
rversion = 101
rerror = 107

-- only 9P2000 is being handled so some constructors are simple
data Message = Tversion
                        | Rversion {size :: Int, tag :: Int,  msize :: Int,
version :: String}
                        | Rerror {message :: String}  -- maybe this should
be Maybe ByteString?

instance Binary Message where
    put Tversion = putWord32le 16 >> tversion >> notag >> msize >> "9P2000"
    put Rversion = putWord32le 16 >> rversion >> notag >> msize >> "9P2000"
    get = do size <- getWord32le
             tag <- getWord8
             case tag of
              rversion -> do msize <- getWord32le
                                   version <- getRemainingLazyByteString
                                   return (Rversion size tag msize (C.unpack


I'm beginning to feel the Get Monad is not going to be as nice as if I had
some bit-syntax for determining what type of return message I'm getting.
 Any "T" message can be met with the paired "R" response, or an Rerror
message, with a detailed description of what went wrong.  My instance of get
is looking like it's going to be pretty nasty :-)

The first message in any 9p session is Tversion with Rversion or Rerror
response.  There's optional authentication hooks via Tauth/Rauth, and then
the filesystem namespace navigation operation messages.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090528/85c2dca2/attachment.html

More information about the Haskell-Cafe mailing list