lib9p

Go 9P library.
Log | Files | Refs | LICENSE

parse.go (3475B)


      1 package lib9p
      2 
      3 import (
      4 	"encoding/binary"
      5 	"fmt"
      6 	"io"
      7 )
      8 
      9 // Read9PMsg reads a 9P message from r and saves it in a byte slice.
     10 // It returns the byte slice read and error if any.
     11 func readMsg(r io.Reader) ([]byte, error) {
     12 	buf := make([]byte, 4)
     13 	read, err := r.Read(buf)
     14 	if err != nil {
     15 		if err == io.EOF {
     16 			return nil, err
     17 		}
     18 		return nil, fmt.Errorf("read size: %v", err)
     19 	}
     20 	if read != len(buf) {
     21 		return buf, fmt.Errorf("read size: invalid message.")
     22 	}
     23 	size := bufMsg(buf).Size()
     24 	mbuf := make([]byte, size-4)
     25 	for read = 0; read < int(size)-4; {
     26 		n, err := r.Read(mbuf[read:])
     27 		if err != nil {
     28 			return buf, fmt.Errorf("read body: %v", err)
     29 		}
     30 		read += n
     31 	}
     32 	buf = append(buf, mbuf...)
     33 	return buf, nil
     34 }
     35 
     36 // unmarshal converts a byte array of 9P message into the corresponding
     37 // Msg struct.
     38 func unmarshal(buf []byte) (Msg, error) {
     39 	switch t := bufMsg(buf).Type(); t {
     40 	case Tversion:
     41 		return newTVersion(buf), nil
     42 	case Rversion:
     43 		return newRVersion(buf), nil
     44 	case Tauth:
     45 		return newTAuth(buf), nil
     46 	case Rauth:
     47 		return newRAuth(buf), nil
     48 	case Tattach:
     49 		return newTAttach(buf), nil
     50 	case Rattach:
     51 		return newRAttach(buf), nil
     52 	case Rerror:
     53 		return newRError(buf), nil
     54 	case Tflush:
     55 		return newTFlush(buf), nil
     56 	case Rflush:
     57 		return newRFlush(buf), nil
     58 	case Twalk:
     59 		return newTWalk(buf), nil
     60 	case Rwalk:
     61 		return newRWalk(buf), nil
     62 	case Topen:
     63 		return newTOpen(buf), nil
     64 	case Ropen:
     65 		return newROpen(buf), nil
     66 	case Tcreate:
     67 		return newTCreate(buf), nil
     68 	case Rcreate:
     69 		return newRCreate(buf), nil
     70 	case Tread:
     71 		return newTRead(buf), nil
     72 	case Rread:
     73 		return newRRead(buf), nil
     74 	case Twrite:
     75 		return newTWrite(buf), nil
     76 	case Rwrite:
     77 		return newRWrite(buf), nil
     78 	case Tclunk:
     79 		return newTClunk(buf), nil
     80 	case Rclunk:
     81 		return newRClunk(buf), nil
     82 	case Tremove:
     83 		return newTRemove(buf), nil
     84 	case Rremove:
     85 		return newRRemove(buf), nil
     86 	case Tstat:
     87 		return newTStat(buf), nil
     88 	case Rstat:
     89 		return newRStat(buf), nil
     90 	case Twstat:
     91 		return newTWstat(buf), nil
     92 	case Rwstat:
     93 		return newRWstat(buf), nil
     94 	default:
     95 		return nil, fmt.Errorf("unknown message type %v", t)
     96 	}
     97 }
     98 
     99 // SendMsg send a 9P message to w
    100 func SendMsg(msg Msg, w io.Writer) error {
    101 	if _, err := w.Write(msg.marshal()); err != nil {
    102 		return fmt.Errorf("write: %v", err)
    103 	}
    104 	return nil
    105 }
    106 
    107 // RecvMsg recievs a 9P message from r.
    108 func RecvMsg(r io.Reader) (Msg, error) {
    109 	b, err := readMsg(r)
    110 	if err == io.EOF {
    111 		return nil, err
    112 	} else if err != nil {
    113 		return nil, fmt.Errorf("readMsg: %v", err)
    114 	}
    115 	return unmarshal(b)
    116 }
    117 
    118 // Gbit16 reads b as 2-byte long little endian unsigned integer and
    119 // returns the result
    120 func gbit16(b []byte) uint16 { return binary.LittleEndian.Uint16(b[0:2]) }
    121 
    122 // Gbit32 reads b as 4-byte long little endian unsigned integer and
    123 // returns the result
    124 func gbit32(b []byte) uint32 { return binary.LittleEndian.Uint32(b[0:4]) }
    125 
    126 // Gbit64 reads b as 8-byte long little endian unsigned integer and
    127 // returns the result
    128 func gbit64(b []byte) uint64 { return binary.LittleEndian.Uint64(b[0:8]) }
    129 
    130 // Pbit16 puts into b an 2-byte long little endian unsigned integer n.
    131 func pbit16(b []byte, n uint16) { binary.LittleEndian.PutUint16(b, n) }
    132 
    133 // Pbit32 puts into b an 4-byte long little endian unsigned integer n.
    134 func pbit32(b []byte, n uint32) { binary.LittleEndian.PutUint32(b, n) }
    135 
    136 // Pbit64 puts into b an 8-byte long little endian unsigned integer n.
    137 func pbit64(b []byte, n uint64) { binary.LittleEndian.PutUint64(b, n) }