diff --git a/pkg/runtime/serializer/protobuf/protobuf.go b/pkg/runtime/serializer/protobuf/protobuf.go index b9eb9e5db86..a21df48a05d 100644 --- a/pkg/runtime/serializer/protobuf/protobuf.go +++ b/pkg/runtime/serializer/protobuf/protobuf.go @@ -124,7 +124,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi if intoUnknown, ok := into.(*runtime.Unknown); ok && intoUnknown != nil { *intoUnknown = unk - if len(intoUnknown.ContentType) == 0 { + if ok, _ := s.RecognizesData(bytes.NewBuffer(unk.Raw)); ok { intoUnknown.ContentType = s.contentType } return intoUnknown, &actual, nil @@ -167,17 +167,30 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi // Encode serializes the provided object to the given writer. func (s *Serializer) Encode(obj runtime.Object, w io.Writer) error { - var unk runtime.Unknown - kind := obj.GetObjectKind().GroupVersionKind() - unk = runtime.Unknown{ - TypeMeta: runtime.TypeMeta{ - Kind: kind.Kind, - APIVersion: kind.GroupVersion().String(), - }, - } - prefixSize := uint64(len(s.prefix)) + var unk runtime.Unknown + switch t := obj.(type) { + case *runtime.Unknown: + estimatedSize := prefixSize + uint64(t.Size()) + data := make([]byte, estimatedSize) + i, err := t.MarshalTo(data[prefixSize:]) + if err != nil { + return err + } + copy(data, s.prefix) + _, err = w.Write(data[:prefixSize+uint64(i)]) + return err + default: + kind := obj.GetObjectKind().GroupVersionKind() + unk = runtime.Unknown{ + TypeMeta: runtime.TypeMeta{ + Kind: kind.Kind, + APIVersion: kind.GroupVersion().String(), + }, + } + } + switch t := obj.(type) { case bufferedMarshaller: // this path performs a single allocation during write but requires the caller to implement diff --git a/pkg/runtime/serializer/protobuf/protobuf_test.go b/pkg/runtime/serializer/protobuf/protobuf_test.go index 54c92bf42a0..77a291da8ec 100644 --- a/pkg/runtime/serializer/protobuf/protobuf_test.go +++ b/pkg/runtime/serializer/protobuf/protobuf_test.go @@ -205,7 +205,7 @@ func TestDecode(t *testing.T) { 0x0a, 0x15, 0x0a, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // apiversion 0x12, 0x04, 0x74, 0x65, 0x73, 0x74, // kind - 0x12, 0x03, 0x01, 0x02, 0x03, // data + 0x12, 0x07, 0x6b, 0x38, 0x73, 0x00, 0x01, 0x02, 0x03, // data 0x1a, 0x00, // content-type 0x22, 0x00, // content-encoding } @@ -227,8 +227,7 @@ func TestDecode(t *testing.T) { }, { obj: &runtime.Unknown{ - ContentType: "application/protobuf", - Raw: []byte{}, + Raw: []byte{}, }, data: wire1, }, @@ -238,8 +237,9 @@ func TestDecode(t *testing.T) { APIVersion: "other/version", Kind: "test", }, + // content type is set because the prefix matches the content ContentType: "application/protobuf", - Raw: []byte{0x01, 0x02, 0x03}, + Raw: []byte{0x6b, 0x38, 0x73, 0x00, 0x01, 0x02, 0x03}, }, data: wire2, },