element.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. Copyright 2018 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 fieldpath
  14. import (
  15. "fmt"
  16. "iter"
  17. "sort"
  18. "strings"
  19. "sigs.k8s.io/structured-merge-diff/v6/value"
  20. )
  21. // PathElement describes how to select a child field given a containing object.
  22. type PathElement struct {
  23. // Exactly one of the following fields should be non-nil.
  24. // FieldName selects a single field from a map (reminder: this is also
  25. // how structs are represented). The containing object must be a map.
  26. FieldName *string
  27. // Key selects the list element which has fields matching those given.
  28. // The containing object must be an associative list with map typed
  29. // elements. They are sorted alphabetically.
  30. Key *value.FieldList
  31. // Value selects the list element with the given value. The containing
  32. // object must be an associative list with a primitive typed element
  33. // (i.e., a set).
  34. Value *value.Value
  35. // Index selects a list element by its index number. The containing
  36. // object must be an atomic list.
  37. Index *int
  38. }
  39. // FieldNameElement creates a new FieldName PathElement.
  40. func FieldNameElement(name string) PathElement {
  41. return PathElement{FieldName: &name}
  42. }
  43. // KeyElement creates a new Key PathElement with the key fields.
  44. func KeyElement(fields ...value.Field) PathElement {
  45. l := value.FieldList(fields)
  46. return PathElement{Key: &l}
  47. }
  48. // KeyElementByFields creates a new Key PathElement from names and values.
  49. // `nameValues` must have an even number of entries, alternating
  50. // names (type must be string) with values (type must be value.Value). If these
  51. // conditions are not met, KeyByFields will panic--it's intended for static
  52. // construction and shouldn't have user-produced values passed to it.
  53. func KeyElementByFields(nameValues ...any) PathElement {
  54. return PathElement{Key: KeyByFields(nameValues...)}
  55. }
  56. // ValueElement creates a new Value PathElement.
  57. func ValueElement(value value.Value) PathElement {
  58. return PathElement{Value: &value}
  59. }
  60. // IndexElement creates a new Index PathElement.
  61. func IndexElement(index int) PathElement {
  62. return PathElement{Index: &index}
  63. }
  64. // Less provides an order for path elements.
  65. func (e PathElement) Less(rhs PathElement) bool {
  66. return e.Compare(rhs) < 0
  67. }
  68. // Compare provides an order for path elements.
  69. func (e PathElement) Compare(rhs PathElement) int {
  70. if e.FieldName != nil {
  71. if rhs.FieldName == nil {
  72. return -1
  73. }
  74. return strings.Compare(*e.FieldName, *rhs.FieldName)
  75. } else if rhs.FieldName != nil {
  76. return 1
  77. }
  78. if e.Key != nil {
  79. if rhs.Key == nil {
  80. return -1
  81. }
  82. return e.Key.Compare(*rhs.Key)
  83. } else if rhs.Key != nil {
  84. return 1
  85. }
  86. if e.Value != nil {
  87. if rhs.Value == nil {
  88. return -1
  89. }
  90. return value.Compare(*e.Value, *rhs.Value)
  91. } else if rhs.Value != nil {
  92. return 1
  93. }
  94. if e.Index != nil {
  95. if rhs.Index == nil {
  96. return -1
  97. }
  98. if *e.Index < *rhs.Index {
  99. return -1
  100. } else if *e.Index == *rhs.Index {
  101. return 0
  102. }
  103. return 1
  104. } else if rhs.Index != nil {
  105. return 1
  106. }
  107. return 0
  108. }
  109. // Equals returns true if both path elements are equal.
  110. func (e PathElement) Equals(rhs PathElement) bool {
  111. if e.FieldName != nil {
  112. if rhs.FieldName == nil {
  113. return false
  114. }
  115. return *e.FieldName == *rhs.FieldName
  116. } else if rhs.FieldName != nil {
  117. return false
  118. }
  119. if e.Key != nil {
  120. if rhs.Key == nil {
  121. return false
  122. }
  123. return e.Key.Equals(*rhs.Key)
  124. } else if rhs.Key != nil {
  125. return false
  126. }
  127. if e.Value != nil {
  128. if rhs.Value == nil {
  129. return false
  130. }
  131. return value.Equals(*e.Value, *rhs.Value)
  132. } else if rhs.Value != nil {
  133. return false
  134. }
  135. if e.Index != nil {
  136. if rhs.Index == nil {
  137. return false
  138. }
  139. return *e.Index == *rhs.Index
  140. } else if rhs.Index != nil {
  141. return false
  142. }
  143. return true
  144. }
  145. // String presents the path element as a human-readable string.
  146. func (e PathElement) String() string {
  147. switch {
  148. case e.FieldName != nil:
  149. return "." + *e.FieldName
  150. case e.Key != nil:
  151. strs := make([]string, len(*e.Key))
  152. for i, k := range *e.Key {
  153. strs[i] = fmt.Sprintf("%v=%v", k.Name, value.ToString(k.Value))
  154. }
  155. // Keys are supposed to be sorted.
  156. return "[" + strings.Join(strs, ",") + "]"
  157. case e.Value != nil:
  158. return fmt.Sprintf("[=%v]", value.ToString(*e.Value))
  159. case e.Index != nil:
  160. return fmt.Sprintf("[%v]", *e.Index)
  161. default:
  162. return "{{invalid path element}}"
  163. }
  164. }
  165. // Copy returns a copy of the PathElement.
  166. // This is not a full deep copy as any contained value.Value is not copied.
  167. func (e PathElement) Copy() PathElement {
  168. if e.FieldName != nil {
  169. return PathElement{FieldName: e.FieldName}
  170. }
  171. if e.Key != nil {
  172. c := e.Key.Copy()
  173. return PathElement{Key: &c}
  174. }
  175. if e.Value != nil {
  176. return PathElement{Value: e.Value}
  177. }
  178. if e.Index != nil {
  179. return PathElement{Index: e.Index}
  180. }
  181. return e // zero value
  182. }
  183. // KeyByFields is a helper function which constructs a key for an associative
  184. // list type. `nameValues` must have an even number of entries, alternating
  185. // names (type must be string) with values (type must be value.Value). If these
  186. // conditions are not met, KeyByFields will panic--it's intended for static
  187. // construction and shouldn't have user-produced values passed to it.
  188. func KeyByFields(nameValues ...interface{}) *value.FieldList {
  189. if len(nameValues)%2 != 0 {
  190. panic("must have a value for every name")
  191. }
  192. out := value.FieldList{}
  193. for i := 0; i < len(nameValues)-1; i += 2 {
  194. out = append(out, value.Field{Name: nameValues[i].(string), Value: value.NewValueInterface(nameValues[i+1])})
  195. }
  196. out.Sort()
  197. return &out
  198. }
  199. // PathElementSet is a set of path elements.
  200. // TODO: serialize as a list.
  201. type PathElementSet struct {
  202. members sortedPathElements
  203. }
  204. func MakePathElementSet(size int) PathElementSet {
  205. return PathElementSet{
  206. members: make(sortedPathElements, 0, size),
  207. }
  208. }
  209. type sortedPathElements []PathElement
  210. // Implement the sort interface; this would permit bulk creation, which would
  211. // be faster than doing it one at a time via Insert.
  212. func (spe sortedPathElements) Len() int { return len(spe) }
  213. func (spe sortedPathElements) Less(i, j int) bool { return spe[i].Less(spe[j]) }
  214. func (spe sortedPathElements) Swap(i, j int) { spe[i], spe[j] = spe[j], spe[i] }
  215. // Copy returns a copy of the PathElementSet.
  216. // This is not a full deep copy as any contained value.Value is not copied.
  217. func (s PathElementSet) Copy() PathElementSet {
  218. out := make(sortedPathElements, len(s.members))
  219. for i := range s.members {
  220. out[i] = s.members[i].Copy()
  221. }
  222. return PathElementSet{members: out}
  223. }
  224. // Insert adds pe to the set.
  225. func (s *PathElementSet) Insert(pe PathElement) {
  226. loc := sort.Search(len(s.members), func(i int) bool {
  227. return !s.members[i].Less(pe)
  228. })
  229. if loc == len(s.members) {
  230. s.members = append(s.members, pe)
  231. return
  232. }
  233. if s.members[loc].Equals(pe) {
  234. return
  235. }
  236. s.members = append(s.members, PathElement{})
  237. copy(s.members[loc+1:], s.members[loc:])
  238. s.members[loc] = pe
  239. }
  240. // Union returns a set containing elements that appear in either s or s2.
  241. func (s *PathElementSet) Union(s2 *PathElementSet) *PathElementSet {
  242. out := &PathElementSet{}
  243. i, j := 0, 0
  244. for i < len(s.members) && j < len(s2.members) {
  245. if s.members[i].Less(s2.members[j]) {
  246. out.members = append(out.members, s.members[i])
  247. i++
  248. } else {
  249. out.members = append(out.members, s2.members[j])
  250. if !s2.members[j].Less(s.members[i]) {
  251. i++
  252. }
  253. j++
  254. }
  255. }
  256. if i < len(s.members) {
  257. out.members = append(out.members, s.members[i:]...)
  258. }
  259. if j < len(s2.members) {
  260. out.members = append(out.members, s2.members[j:]...)
  261. }
  262. return out
  263. }
  264. // Intersection returns a set containing elements which appear in both s and s2.
  265. func (s *PathElementSet) Intersection(s2 *PathElementSet) *PathElementSet {
  266. out := &PathElementSet{}
  267. i, j := 0, 0
  268. for i < len(s.members) && j < len(s2.members) {
  269. if s.members[i].Less(s2.members[j]) {
  270. i++
  271. } else {
  272. if !s2.members[j].Less(s.members[i]) {
  273. out.members = append(out.members, s.members[i])
  274. i++
  275. }
  276. j++
  277. }
  278. }
  279. return out
  280. }
  281. // Difference returns a set containing elements which appear in s but not in s2.
  282. func (s *PathElementSet) Difference(s2 *PathElementSet) *PathElementSet {
  283. out := &PathElementSet{}
  284. i, j := 0, 0
  285. for i < len(s.members) && j < len(s2.members) {
  286. if s.members[i].Less(s2.members[j]) {
  287. out.members = append(out.members, s.members[i])
  288. i++
  289. } else {
  290. if !s2.members[j].Less(s.members[i]) {
  291. i++
  292. }
  293. j++
  294. }
  295. }
  296. if i < len(s.members) {
  297. out.members = append(out.members, s.members[i:]...)
  298. }
  299. return out
  300. }
  301. // Size retuns the number of elements in the set.
  302. func (s *PathElementSet) Size() int { return len(s.members) }
  303. // Has returns true if pe is a member of the set.
  304. func (s *PathElementSet) Has(pe PathElement) bool {
  305. loc := sort.Search(len(s.members), func(i int) bool {
  306. return !s.members[i].Less(pe)
  307. })
  308. if loc == len(s.members) {
  309. return false
  310. }
  311. if s.members[loc].Equals(pe) {
  312. return true
  313. }
  314. return false
  315. }
  316. // Equals returns true if s and s2 have exactly the same members.
  317. func (s *PathElementSet) Equals(s2 *PathElementSet) bool {
  318. if len(s.members) != len(s2.members) {
  319. return false
  320. }
  321. for k := range s.members {
  322. if !s.members[k].Equals(s2.members[k]) {
  323. return false
  324. }
  325. }
  326. return true
  327. }
  328. // Iterate calls f for each PathElement in the set. The order is deterministic.
  329. func (s *PathElementSet) Iterate(f func(PathElement)) {
  330. for _, pe := range s.members {
  331. f(pe)
  332. }
  333. }
  334. // All iterates over each PathElement in the set. The order is deterministic.
  335. func (s *PathElementSet) All() iter.Seq[PathElement] {
  336. return func(yield func(element PathElement) bool) {
  337. for _, pe := range s.members {
  338. if !yield(pe) {
  339. return
  340. }
  341. }
  342. }
  343. }