package govmtools import ( "bytes" "encoding/binary" "fmt" ) type Field struct { Type FieldType ID FieldID Value interface{} } func (s *Socket) WritePacket(pkt []Field) error { buf := bytes.NewBuffer(nil) for _, field := range pkt { err := binary.Write(buf, order, field.Type) if err != nil { return fmt.Errorf("write field type: %w", err) } if field.Type == FieldEmpty { continue } err = binary.Write(buf, order, field.ID) if err != nil { return fmt.Errorf("write field ID: %w", err) } switch field.Type { case FieldInt64: err = binary.Write(buf, order, field.Value) if err != nil { return fmt.Errorf("write int64: %w", err) } case FieldString: val := field.Value.(string) err = binary.Write(buf, order, int32(len(val))) if err != nil { return fmt.Errorf("write string len: %w", err) } _, err = buf.WriteString(val) if err != nil { return fmt.Errorf("write string: %w", err) } } } res := make([]byte, buf.Len()+4) order.PutUint32(res, uint32(buf.Len())) copy(res[4:], buf.Bytes()) _, err := s.conn.Write(res) if err != nil { return fmt.Errorf("write: %w", err) } return nil } func (s *Socket) ReadPacket() ([]Field, error) { length := make([]byte, 4) _, err := s.conn.Read(length) if err != nil { return nil, fmt.Errorf("read len: %w", err) } response := make([]byte, order.Uint32(length)) _, err = s.conn.Read(response) if err != nil { return nil, fmt.Errorf("read: %w", err) } buf := bytes.NewBuffer(response) var fields []Field for buf.Len() > 0 { field := Field{} err = binary.Read(buf, order, &field.Type) if err != nil { return nil, fmt.Errorf("parse field type: %w", err) } if field.Type == FieldEmpty { continue } err = binary.Read(buf, order, &field.ID) if err != nil { return nil, fmt.Errorf("parse field ID: %w", err) } switch field.Type { case FieldInt64: var val int64 err = binary.Read(buf, order, val) if err != nil { return nil, fmt.Errorf("parse int64: %w", err) } field.Value = val case FieldString: var length uint32 err = binary.Read(buf, order, &length) if err != nil { return nil, fmt.Errorf("parse string length: %w", err) } byt := make([]byte, length) _, err := buf.Read(byt) if err != nil { return nil, fmt.Errorf("parse string: %w", err) } field.Value = string(byt) } fields = append(fields, field) } return fields, nil }