Writing instances encode/decode that use either little endian or big endian (or mixed!) is trivial... see attached file.
 
I don't see where your problem is...
 
On Thu, May 28, 2009 at 12:35 PM, David Leimbach <leimy2k@gmail.com> wrote:


On Thu, May 28, 2009 at 9:17 AM, John Van Enk <vanenkj@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 Data.Binary)

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

 ===========

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.

Dave

/jve


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
/jve