package cli import ( "bytes" "encoding/binary" "git.nspix.com/golang/micro/helper/unsafestr" "io" ) var ( feature = []byte{67, 76, 73} ) const ( PacketTypeCompleter byte = 0x01 PacketTypeData = 0x02 PacketTypeEcho = 0x03 ) type Frame struct { Feature []byte Type byte `json:"type"` Data []byte `json:"data"` Error string `json:"error"` Timestamp int64 `json:"timestamp"` } func readFrame(r io.Reader) (frame *Frame, err error) { var ( n int dataLength int16 errorLength int16 errBuf []byte ) frame = &Frame{Feature: make([]byte, 3)} if _, err = io.ReadFull(r, frame.Feature); err != nil { return } if !bytes.Equal(frame.Feature, feature) { err = io.ErrUnexpectedEOF return } if err = binary.Read(r, binary.LittleEndian, &frame.Type); err != nil { return } if err = binary.Read(r, binary.LittleEndian, &frame.Timestamp); err != nil { return } if err = binary.Read(r, binary.LittleEndian, &dataLength); err != nil { return } if err = binary.Read(r, binary.LittleEndian, &errorLength); err != nil { return } if dataLength > 0 { frame.Data = make([]byte, dataLength) if n, err = io.ReadFull(r, frame.Data); err == nil { if n < int(dataLength) { err = io.ErrShortBuffer } } } if errorLength > 0 { errBuf = make([]byte, errorLength) if n, err = io.ReadFull(r, errBuf); err == nil { if n < int(dataLength) { err = io.ErrShortBuffer } else { frame.Error = unsafestr.BytesToString(errBuf) } } } return } func writeFrame(w io.Writer, frame *Frame) (err error) { var ( n int dataLength int16 errorLength int16 errBuf []byte ) if _, err = w.Write(feature); err != nil { return } if frame.Data != nil { dataLength = int16(len(frame.Data)) } if frame.Error != "" { errBuf = unsafestr.StringToBytes(frame.Error) errorLength = int16(len(errBuf)) } if err = binary.Write(w, binary.LittleEndian, frame.Type); err != nil { return } if err = binary.Write(w, binary.LittleEndian, frame.Timestamp); err != nil { return } if err = binary.Write(w, binary.LittleEndian, dataLength); err != nil { return } if err = binary.Write(w, binary.LittleEndian, errorLength); err != nil { return } if dataLength > 0 { if n, err = w.Write(frame.Data); err == nil { if n < int(dataLength) { err = io.ErrShortWrite } } } if errorLength > 0 { if n, err = w.Write(errBuf); err == nil { if n < int(errorLength) { err = io.ErrShortWrite } } } return }