@@ -20,12 +20,42 @@ import (
20
20
"bytes"
21
21
"errors"
22
22
23
+ cbor "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
23
24
"k8s.io/apimachinery/pkg/util/json"
24
25
)
25
26
26
27
var jsTrue = []byte ("true" )
27
28
var jsFalse = []byte ("false" )
28
29
30
+ // The CBOR parsing related constants and functions below are not exported so they can be
31
+ // easily removed at a future date when the CBOR library provides equivalent functionality.
32
+
33
+ type cborMajorType int
34
+
35
+ const (
36
+ // https://www.rfc-editor.org/rfc/rfc8949.html#section-3.1
37
+ cborUnsignedInteger cborMajorType = 0
38
+ cborNegativeInteger cborMajorType = 1
39
+ cborByteString cborMajorType = 2
40
+ cborTextString cborMajorType = 3
41
+ cborArray cborMajorType = 4
42
+ cborMap cborMajorType = 5
43
+ cborTag cborMajorType = 6
44
+ cborOther cborMajorType = 7
45
+ )
46
+
47
+ const (
48
+ // from https://www.rfc-editor.org/rfc/rfc8949.html#name-jump-table-for-initial-byte.
49
+ // additionally, see https://www.rfc-editor.org/rfc/rfc8949.html#section-3.3-5.
50
+ cborFalseValue = 0xf4
51
+ cborTrueValue = 0xf5
52
+ cborNullValue = 0xf6
53
+ )
54
+
55
+ func cborType (b byte ) cborMajorType {
56
+ return cborMajorType (b >> 5 )
57
+ }
58
+
29
59
func (s JSONSchemaPropsOrBool ) MarshalJSON () ([]byte , error ) {
30
60
if s .Schema != nil {
31
61
return json .Marshal (s .Schema )
@@ -59,6 +89,39 @@ func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
59
89
return nil
60
90
}
61
91
92
+ func (s JSONSchemaPropsOrBool ) MarshalCBOR () ([]byte , error ) {
93
+ if s .Schema != nil {
94
+ return cbor .Marshal (s .Schema )
95
+ }
96
+ return cbor .Marshal (s .Allows )
97
+ }
98
+
99
+ func (s * JSONSchemaPropsOrBool ) UnmarshalCBOR (data []byte ) error {
100
+ switch {
101
+ case len (data ) == 0 :
102
+ // ideally we would avoid modifying *s here, but we are matching the behavior of UnmarshalJSON
103
+ * s = JSONSchemaPropsOrBool {}
104
+ return nil
105
+ case cborType (data [0 ]) == cborMap :
106
+ var p JSONSchemaProps
107
+ if err := cbor .Unmarshal (data , & p ); err != nil {
108
+ return err
109
+ }
110
+ * s = JSONSchemaPropsOrBool {Allows : true , Schema : & p }
111
+ return nil
112
+ case data [0 ] == cborTrueValue :
113
+ * s = JSONSchemaPropsOrBool {Allows : true }
114
+ return nil
115
+ case data [0 ] == cborFalseValue :
116
+ * s = JSONSchemaPropsOrBool {Allows : false }
117
+ return nil
118
+ default :
119
+ // ideally, this case would not also capture a null input value,
120
+ // but we are matching the behavior of the UnmarshalJSON
121
+ return errors .New ("boolean or JSON schema expected" )
122
+ }
123
+ }
124
+
62
125
func (s JSONSchemaPropsOrStringArray ) MarshalJSON () ([]byte , error ) {
63
126
if len (s .Property ) > 0 {
64
127
return json .Marshal (s .Property )
@@ -91,6 +154,40 @@ func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
91
154
return nil
92
155
}
93
156
157
+ func (s JSONSchemaPropsOrStringArray ) MarshalCBOR () ([]byte , error ) {
158
+ if len (s .Property ) > 0 {
159
+ return cbor .Marshal (s .Property )
160
+ }
161
+ if s .Schema != nil {
162
+ return cbor .Marshal (s .Schema )
163
+ }
164
+ return cbor .Marshal (nil )
165
+ }
166
+
167
+ func (s * JSONSchemaPropsOrStringArray ) UnmarshalCBOR (data []byte ) error {
168
+ if len (data ) > 0 && cborType (data [0 ]) == cborArray {
169
+ var a []string
170
+ if err := cbor .Unmarshal (data , & a ); err != nil {
171
+ return err
172
+ }
173
+ * s = JSONSchemaPropsOrStringArray {Property : a }
174
+ return nil
175
+ }
176
+ if len (data ) > 0 && cborType (data [0 ]) == cborMap {
177
+ var p JSONSchemaProps
178
+ if err := cbor .Unmarshal (data , & p ); err != nil {
179
+ return err
180
+ }
181
+ * s = JSONSchemaPropsOrStringArray {Schema : & p }
182
+ return nil
183
+ }
184
+ // At this point we either have: empty data, a null value, or an
185
+ // unexpected type. In order to match the behavior of the existing
186
+ // UnmarshalJSON, no error is returned and *s is overwritten here.
187
+ * s = JSONSchemaPropsOrStringArray {}
188
+ return nil
189
+ }
190
+
94
191
func (s JSONSchemaPropsOrArray ) MarshalJSON () ([]byte , error ) {
95
192
if len (s .JSONSchemas ) > 0 {
96
193
return json .Marshal (s .JSONSchemas )
@@ -120,6 +217,37 @@ func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
120
217
return nil
121
218
}
122
219
220
+ func (s JSONSchemaPropsOrArray ) MarshalCBOR () ([]byte , error ) {
221
+ if len (s .JSONSchemas ) > 0 {
222
+ return cbor .Marshal (s .JSONSchemas )
223
+ }
224
+ return cbor .Marshal (s .Schema )
225
+ }
226
+
227
+ func (s * JSONSchemaPropsOrArray ) UnmarshalCBOR (data []byte ) error {
228
+ if len (data ) > 0 && cborType (data [0 ]) == cborMap {
229
+ var p JSONSchemaProps
230
+ if err := cbor .Unmarshal (data , & p ); err != nil {
231
+ return err
232
+ }
233
+ * s = JSONSchemaPropsOrArray {Schema : & p }
234
+ return nil
235
+ }
236
+ if len (data ) > 0 && cborType (data [0 ]) == cborArray {
237
+ var a []JSONSchemaProps
238
+ if err := cbor .Unmarshal (data , & a ); err != nil {
239
+ return err
240
+ }
241
+ * s = JSONSchemaPropsOrArray {JSONSchemas : a }
242
+ return nil
243
+ }
244
+ // At this point we either have: empty data, a null value, or an
245
+ // unexpected type. In order to match the behavior of the existing
246
+ // UnmarshalJSON, no error is returned and *s is overwritten here.
247
+ * s = JSONSchemaPropsOrArray {}
248
+ return nil
249
+ }
250
+
123
251
func (s JSON ) MarshalJSON () ([]byte , error ) {
124
252
if len (s .Raw ) > 0 {
125
253
return s .Raw , nil
@@ -134,3 +262,34 @@ func (s *JSON) UnmarshalJSON(data []byte) error {
134
262
}
135
263
return nil
136
264
}
265
+
266
+ func (s JSON ) MarshalCBOR () ([]byte , error ) {
267
+ // Note that non-semantic whitespace is lost during the transcoding performed here.
268
+ // We do not forsee this to be a problem given the current known uses of this type.
269
+ // Other limitations that arise when roundtripping JSON via dynamic clients also apply
270
+ // here, for example: insignificant whitespace handling, number handling, and map key ordering.
271
+ if len (s .Raw ) == 0 {
272
+ return []byte {cborNullValue }, nil
273
+ }
274
+ var u any
275
+ if err := json .Unmarshal (s .Raw , & u ); err != nil {
276
+ return nil , err
277
+ }
278
+ return cbor .Marshal (u )
279
+ }
280
+
281
+ func (s * JSON ) UnmarshalCBOR (data []byte ) error {
282
+ if len (data ) == 0 || data [0 ] == cborNullValue {
283
+ return nil
284
+ }
285
+ var u any
286
+ if err := cbor .Unmarshal (data , & u ); err != nil {
287
+ return err
288
+ }
289
+ raw , err := json .Marshal (u )
290
+ if err != nil {
291
+ return err
292
+ }
293
+ s .Raw = raw
294
+ return nil
295
+ }
0 commit comments