raw.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. Copyright 2024 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package cbor
  14. import (
  15. "fmt"
  16. "reflect"
  17. "sync"
  18. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  19. "k8s.io/apimachinery/pkg/runtime"
  20. )
  21. var sharedTranscoders transcoders
  22. var rawTypeTranscodeFuncs = map[reflect.Type]func(reflect.Value) error{
  23. reflect.TypeFor[runtime.RawExtension](): func(rv reflect.Value) error {
  24. if !rv.CanAddr() {
  25. return nil
  26. }
  27. re := rv.Addr().Interface().(*runtime.RawExtension)
  28. if re.Raw == nil {
  29. // When Raw is nil it encodes to null. Don't change nil Raw values during
  30. // transcoding, they would have unmarshalled from JSON as nil too.
  31. return nil
  32. }
  33. j, err := re.MarshalJSON()
  34. if err != nil {
  35. return fmt.Errorf("failed to transcode RawExtension to JSON: %w", err)
  36. }
  37. re.Raw = j
  38. return nil
  39. },
  40. reflect.TypeFor[metav1.FieldsV1](): func(rv reflect.Value) error {
  41. if !rv.CanAddr() {
  42. return nil
  43. }
  44. fields := rv.Addr().Interface().(*metav1.FieldsV1)
  45. if fields.Raw == nil {
  46. // When Raw is nil it encodes to null. Don't change nil Raw values during
  47. // transcoding, they would have unmarshalled from JSON as nil too.
  48. return nil
  49. }
  50. j, err := fields.MarshalJSON()
  51. if err != nil {
  52. return fmt.Errorf("failed to transcode FieldsV1 to JSON: %w", err)
  53. }
  54. fields.Raw = j
  55. return nil
  56. },
  57. }
  58. func transcodeRawTypes(v interface{}) error {
  59. if v == nil {
  60. return nil
  61. }
  62. rv := reflect.ValueOf(v)
  63. return sharedTranscoders.getTranscoder(rv.Type()).fn(rv)
  64. }
  65. type transcoder struct {
  66. fn func(rv reflect.Value) error
  67. }
  68. var noop = transcoder{
  69. fn: func(reflect.Value) error {
  70. return nil
  71. },
  72. }
  73. type transcoders struct {
  74. lock sync.RWMutex
  75. m map[reflect.Type]**transcoder
  76. }
  77. func (ts *transcoders) getTranscoder(rt reflect.Type) transcoder {
  78. ts.lock.RLock()
  79. tpp, ok := ts.m[rt]
  80. ts.lock.RUnlock()
  81. if ok {
  82. return **tpp
  83. }
  84. ts.lock.Lock()
  85. defer ts.lock.Unlock()
  86. tp := ts.getTranscoderLocked(rt)
  87. return *tp
  88. }
  89. func (ts *transcoders) getTranscoderLocked(rt reflect.Type) *transcoder {
  90. if tpp, ok := ts.m[rt]; ok {
  91. // A transcoder for this type was cached while waiting to acquire the lock.
  92. return *tpp
  93. }
  94. // Cache the transcoder now, before populating fn, so that circular references between types
  95. // don't overflow the call stack.
  96. t := new(transcoder)
  97. if ts.m == nil {
  98. ts.m = make(map[reflect.Type]**transcoder)
  99. }
  100. ts.m[rt] = &t
  101. for rawType, fn := range rawTypeTranscodeFuncs {
  102. if rt == rawType {
  103. t = &transcoder{fn: fn}
  104. return t
  105. }
  106. }
  107. switch rt.Kind() {
  108. case reflect.Array:
  109. te := ts.getTranscoderLocked(rt.Elem())
  110. rtlen := rt.Len()
  111. if rtlen == 0 || te == &noop {
  112. t = &noop
  113. break
  114. }
  115. t.fn = func(rv reflect.Value) error {
  116. for i := 0; i < rtlen; i++ {
  117. if err := te.fn(rv.Index(i)); err != nil {
  118. return err
  119. }
  120. }
  121. return nil
  122. }
  123. case reflect.Interface:
  124. // Any interface value might have a dynamic type involving RawExtension. It needs to
  125. // be checked.
  126. t.fn = func(rv reflect.Value) error {
  127. if rv.IsNil() {
  128. return nil
  129. }
  130. rv = rv.Elem()
  131. // The interface element's type is dynamic so its transcoder can't be
  132. // determined statically.
  133. return ts.getTranscoder(rv.Type()).fn(rv)
  134. }
  135. case reflect.Map:
  136. rtk := rt.Key()
  137. tk := ts.getTranscoderLocked(rtk)
  138. rte := rt.Elem()
  139. te := ts.getTranscoderLocked(rte)
  140. if tk == &noop && te == &noop {
  141. t = &noop
  142. break
  143. }
  144. t.fn = func(rv reflect.Value) error {
  145. iter := rv.MapRange()
  146. rvk := reflect.New(rtk).Elem()
  147. rve := reflect.New(rte).Elem()
  148. for iter.Next() {
  149. rvk.SetIterKey(iter)
  150. if err := tk.fn(rvk); err != nil {
  151. return err
  152. }
  153. rve.SetIterValue(iter)
  154. if err := te.fn(rve); err != nil {
  155. return err
  156. }
  157. }
  158. return nil
  159. }
  160. case reflect.Pointer:
  161. te := ts.getTranscoderLocked(rt.Elem())
  162. if te == &noop {
  163. t = &noop
  164. break
  165. }
  166. t.fn = func(rv reflect.Value) error {
  167. if rv.IsNil() {
  168. return nil
  169. }
  170. return te.fn(rv.Elem())
  171. }
  172. case reflect.Slice:
  173. te := ts.getTranscoderLocked(rt.Elem())
  174. if te == &noop {
  175. t = &noop
  176. break
  177. }
  178. t.fn = func(rv reflect.Value) error {
  179. for i := 0; i < rv.Len(); i++ {
  180. if err := te.fn(rv.Index(i)); err != nil {
  181. return err
  182. }
  183. }
  184. return nil
  185. }
  186. case reflect.Struct:
  187. type fieldTranscoder struct {
  188. Index int
  189. Transcoder *transcoder
  190. }
  191. var fieldTranscoders []fieldTranscoder
  192. for i := 0; i < rt.NumField(); i++ {
  193. f := rt.Field(i)
  194. tf := ts.getTranscoderLocked(f.Type)
  195. if tf == &noop {
  196. continue
  197. }
  198. fieldTranscoders = append(fieldTranscoders, fieldTranscoder{Index: i, Transcoder: tf})
  199. }
  200. if len(fieldTranscoders) == 0 {
  201. t = &noop
  202. break
  203. }
  204. t.fn = func(rv reflect.Value) error {
  205. for _, ft := range fieldTranscoders {
  206. if err := ft.Transcoder.fn(rv.Field(ft.Index)); err != nil {
  207. return err
  208. }
  209. }
  210. return nil
  211. }
  212. default:
  213. t = &noop
  214. }
  215. return t
  216. }