package core import ( "encoding/binary" "fmt" "io" "net" "strings" ) func Send(conn net.Conn, dataType DataType, data Marshaler) error { packet := []any{uint8(dataType)} packet = append(packet, data.Marshal()...) for _, v := range packet { err := binary.Write(conn, binary.BigEndian, v) if err != nil { return fmt.Errorf("cannot send: %v", err) } } return nil } func Read(r io.Reader) (any, error) { dType, err := ReadDataType(r) if err != nil { return nil, fmt.Errorf("cannot read data type", err) } switch dType { case TypeUnknown: return nil, fmt.Errorf("cannot read data type 0x00 (TypeUnknown)") case TypeHandshake: return ReadHandshake(r) case TypeTest: return ReadTest(r) default: return nil, fmt.Errorf("unsupported type: %v", dType) } } func ReadDataType(r io.Reader) (DataType, error) { var data uint8 if err := read(r, &data); err != nil { return TypeUnknown, err } dType := DataType(data) return dType, nil } func ReadHandshake(r io.Reader) (Handshake, error) { var d Handshake err := read(r, &d.Version) return d, err } func ReadTest(r io.Reader) (Test, error) { var d Test err := readString(r, &d.Message) return d, err } func readString(r io.Reader, ptr *string) error { var ( sb strings.Builder buf byte ) for { if err := read(r, &buf); err != nil { return err } if buf == 0x0 { break } if err := sb.WriteByte(buf); err != nil { fmt.Errorf("cannot write byte to string buffer: %v", err) } } *ptr = sb.String() return nil } func read(r io.Reader, ptr any) error { err := binary.Read(r, binary.BigEndian, ptr) if err != nil { return fmt.Errorf("cannot read: %v", err) } return nil }