2 Copyright 2014 The Kubernetes Authors.
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
24 "k8s.io/apimachinery/pkg/conversion"
25 "k8s.io/apimachinery/pkg/runtime/schema"
26 "k8s.io/apimachinery/pkg/util/errors"
29 // unsafeObjectConvertor implements ObjectConvertor using the unsafe conversion path.
30 type unsafeObjectConvertor struct {
34 var _ ObjectConvertor = unsafeObjectConvertor{}
36 // ConvertToVersion converts in to the provided outVersion without copying the input first, which
37 // is only safe if the output object is not mutated or reused.
38 func (c unsafeObjectConvertor) ConvertToVersion(in Object, outVersion GroupVersioner) (Object, error) {
39 return c.Scheme.UnsafeConvertToVersion(in, outVersion)
42 // UnsafeObjectConvertor performs object conversion without copying the object structure,
43 // for use when the converted object will not be reused or mutated. Primarily for use within
44 // versioned codecs, which use the external object for serialization but do not return it.
45 func UnsafeObjectConvertor(scheme *Scheme) ObjectConvertor {
46 return unsafeObjectConvertor{scheme}
49 // SetField puts the value of src, into fieldName, which must be a member of v.
50 // The value of src must be assignable to the field.
51 func SetField(src interface{}, v reflect.Value, fieldName string) error {
52 field := v.FieldByName(fieldName)
54 return fmt.Errorf("couldn't find %v field in %#v", fieldName, v.Interface())
56 srcValue := reflect.ValueOf(src)
57 if srcValue.Type().AssignableTo(field.Type()) {
61 if srcValue.Type().ConvertibleTo(field.Type()) {
62 field.Set(srcValue.Convert(field.Type()))
65 return fmt.Errorf("couldn't assign/convert %v to %v", srcValue.Type(), field.Type())
68 // Field puts the value of fieldName, which must be a member of v, into dest,
69 // which must be a variable to which this field's value can be assigned.
70 func Field(v reflect.Value, fieldName string, dest interface{}) error {
71 field := v.FieldByName(fieldName)
73 return fmt.Errorf("couldn't find %v field in %#v", fieldName, v.Interface())
75 destValue, err := conversion.EnforcePtr(dest)
79 if field.Type().AssignableTo(destValue.Type()) {
83 if field.Type().ConvertibleTo(destValue.Type()) {
84 destValue.Set(field.Convert(destValue.Type()))
87 return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), destValue.Type())
90 // FieldPtr puts the address of fieldName, which must be a member of v,
91 // into dest, which must be an address of a variable to which this field's
92 // address can be assigned.
93 func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error {
94 field := v.FieldByName(fieldName)
96 return fmt.Errorf("couldn't find %v field in %#v", fieldName, v.Interface())
98 v, err := conversion.EnforcePtr(dest)
103 if field.Type().AssignableTo(v.Type()) {
107 if field.Type().ConvertibleTo(v.Type()) {
108 v.Set(field.Convert(v.Type()))
111 return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), v.Type())
114 // EncodeList ensures that each object in an array is converted to a Unknown{} in serialized form.
115 // TODO: accept a content type.
116 func EncodeList(e Encoder, objects []Object) error {
118 for i := range objects {
119 data, err := Encode(e, objects[i])
121 errs = append(errs, err)
124 // TODO: Set ContentEncoding and ContentType.
125 objects[i] = &Unknown{Raw: data}
127 return errors.NewAggregate(errs)
130 func decodeListItem(obj *Unknown, decoders []Decoder) (Object, error) {
131 for _, decoder := range decoders {
132 // TODO: Decode based on ContentType.
133 obj, err := Decode(decoder, obj.Raw)
135 if IsNotRegisteredError(err) {
142 // could not decode, so leave the object as Unknown, but give the decoders the
143 // chance to set Unknown.TypeMeta if it is available.
144 for _, decoder := range decoders {
145 if err := DecodeInto(decoder, obj.Raw, obj); err == nil {
152 // DecodeList alters the list in place, attempting to decode any objects found in
153 // the list that have the Unknown type. Any errors that occur are returned
154 // after the entire list is processed. Decoders are tried in order.
155 func DecodeList(objects []Object, decoders ...Decoder) []error {
157 for i, obj := range objects {
158 switch t := obj.(type) {
160 decoded, err := decodeListItem(t, decoders)
162 errs = append(errs, err)
171 // MultiObjectTyper returns the types of objects across multiple schemes in order.
172 type MultiObjectTyper []ObjectTyper
174 var _ ObjectTyper = MultiObjectTyper{}
176 func (m MultiObjectTyper) ObjectKinds(obj Object) (gvks []schema.GroupVersionKind, unversionedType bool, err error) {
177 for _, t := range m {
178 gvks, unversionedType, err = t.ObjectKinds(obj)
186 func (m MultiObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
187 for _, t := range m {
188 if t.Recognizes(gvk) {
195 // SetZeroValue would set the object of objPtr to zero value of its type.
196 func SetZeroValue(objPtr Object) error {
197 v, err := conversion.EnforcePtr(objPtr)
201 v.Set(reflect.Zero(v.Type()))
205 // DefaultFramer is valid for any stream that can read objects serially without
206 // any separation in the stream.
207 var DefaultFramer = defaultFramer{}
209 type defaultFramer struct{}
211 func (defaultFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser { return r }
212 func (defaultFramer) NewFrameWriter(w io.Writer) io.Writer { return w }