mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 14:37:00 +00:00
Merge pull request #128462 from benluddy/cbor-direct-custom-marshalers
KEP-4222: Reject custom marshalers from direct CBOR Marshal and Unmarshal.
This commit is contained in:
commit
f0ff870871
@ -23,14 +23,39 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes"
|
||||
)
|
||||
|
||||
// Marshal serializes a value to CBOR. If there is more than one way to encode the value, it will
|
||||
// make the same choice as the CBOR implementation of runtime.Serializer.
|
||||
//
|
||||
// Note: Support for CBOR is at an alpha stage. If the value (or, for composite types, any of its
|
||||
// nested values) implement any of the interfaces encoding.TextMarshaler, encoding.TextUnmarshaler,
|
||||
// encoding/json.Marshaler, or encoding/json.Unmarshaler, a non-nil error will be returned unless
|
||||
// the value also implements the corresponding CBOR interfaces. This limitation will ultimately be
|
||||
// removed in favor of automatic transcoding to CBOR.
|
||||
func Marshal(src interface{}) ([]byte, error) {
|
||||
if err := modes.RejectCustomMarshalers(src); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modes.Encode.Marshal(src)
|
||||
}
|
||||
|
||||
// Unmarshal deserializes from CBOR into an addressable value. If there is more than one way to
|
||||
// unmarshal a value, it will make the same choice as the CBOR implementation of runtime.Serializer.
|
||||
//
|
||||
// Note: Support for CBOR is at an alpha stage. If the value (or, for composite types, any of its
|
||||
// nested values) implement any of the interfaces encoding.TextMarshaler, encoding.TextUnmarshaler,
|
||||
// encoding/json.Marshaler, or encoding/json.Unmarshaler, a non-nil error will be returned unless
|
||||
// the value also implements the corresponding CBOR interfaces. This limitation will ultimately be
|
||||
// removed in favor of automatic transcoding to CBOR.
|
||||
func Unmarshal(src []byte, dst interface{}) error {
|
||||
if err := modes.RejectCustomMarshalers(dst); err != nil {
|
||||
return err
|
||||
}
|
||||
return modes.Decode.Unmarshal(src, dst)
|
||||
}
|
||||
|
||||
// Diagnose accepts well-formed CBOR bytes and returns a string representing the same data item in
|
||||
// human-readable diagnostic notation (RFC 8949 Section 8). The diagnostic notation is not meant to
|
||||
// be parsed.
|
||||
func Diagnose(src []byte) (string, error) {
|
||||
return modes.Diagnostic.Diagnose(src)
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2024 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package direct_test
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
|
||||
)
|
||||
|
||||
var _ json.Marshaler = CustomJSONMarshaler{}
|
||||
|
||||
type CustomJSONMarshaler struct{}
|
||||
|
||||
func (CustomJSONMarshaler) MarshalJSON() ([]byte, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var _ json.Unmarshaler = CustomJSONUnmarshaler{}
|
||||
|
||||
type CustomJSONUnmarshaler struct{}
|
||||
|
||||
func (CustomJSONUnmarshaler) UnmarshalJSON([]byte) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var _ encoding.TextMarshaler = CustomTextMarshaler{}
|
||||
|
||||
type CustomTextMarshaler struct{}
|
||||
|
||||
func (CustomTextMarshaler) MarshalText() ([]byte, error) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
var _ encoding.TextUnmarshaler = CustomTextUnmarshaler{}
|
||||
|
||||
type CustomTextUnmarshaler struct{}
|
||||
|
||||
func (CustomTextUnmarshaler) UnmarshalText([]byte) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
||||
func TestRejectsCustom(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
value interface{}
|
||||
iface reflect.Type
|
||||
}{
|
||||
{value: CustomJSONMarshaler{}, iface: reflect.TypeFor[json.Marshaler]()},
|
||||
{value: CustomJSONUnmarshaler{}, iface: reflect.TypeFor[json.Unmarshaler]()},
|
||||
{value: CustomTextMarshaler{}, iface: reflect.TypeFor[encoding.TextMarshaler]()},
|
||||
{value: CustomTextUnmarshaler{}, iface: reflect.TypeFor[encoding.TextUnmarshaler]()},
|
||||
} {
|
||||
t.Run(fmt.Sprintf("%T", tc.value), func(t *testing.T) {
|
||||
want := fmt.Sprintf("unable to serialize %T: %T implements %s without corresponding cbor interface", tc.value, tc.value, tc.iface.String())
|
||||
if _, err := direct.Marshal(tc.value); err == nil || err.Error() != want {
|
||||
t.Errorf("want error: %q, got: %v", want, err)
|
||||
}
|
||||
if err := direct.Unmarshal(nil, tc.value); err == nil || err.Error() != want {
|
||||
t.Errorf("want error: %q, got: %v", want, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user