
On Thu, May 28, 2009 at 11:39 AM, John Van Enk
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...
Inexperience, lack of enough contiguous time to digest everything at once (till now), thank you for your most detailed example! This should be wiki'd. Dave
On Thu, May 28, 2009 at 12:35 PM, David Leimbach
wrote: On Thu, May 28, 2009 at 9:17 AM, John Van Enk
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