path.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. "strings"
  17. "sigs.k8s.io/structured-merge-diff/value"
  18. )
  19. // Path describes how to select a potentially deeply-nested child field given a
  20. // containing object.
  21. type Path []PathElement
  22. func (fp Path) String() string {
  23. strs := make([]string, len(fp))
  24. for i := range fp {
  25. strs[i] = fp[i].String()
  26. }
  27. return strings.Join(strs, "")
  28. }
  29. func (fp Path) Copy() Path {
  30. new := make(Path, len(fp))
  31. copy(new, fp)
  32. return new
  33. }
  34. // MakePath constructs a Path. The parts may be PathElements, ints, strings.
  35. func MakePath(parts ...interface{}) (Path, error) {
  36. var fp Path
  37. for _, p := range parts {
  38. switch t := p.(type) {
  39. case PathElement:
  40. fp = append(fp, t)
  41. case int:
  42. // TODO: Understand schema and object and convert this to the
  43. // FieldSpecifier below if appropriate.
  44. fp = append(fp, PathElement{Index: &t})
  45. case string:
  46. fp = append(fp, PathElement{FieldName: &t})
  47. case []value.Field:
  48. if len(t) == 0 {
  49. return nil, fmt.Errorf("associative list key type path elements must have at least one key (got zero)")
  50. }
  51. fp = append(fp, PathElement{Key: t})
  52. case value.Value:
  53. // TODO: understand schema and verify that this is a set type
  54. // TODO: make a copy of t
  55. fp = append(fp, PathElement{Value: &t})
  56. default:
  57. return nil, fmt.Errorf("unable to make %#v into a path element", p)
  58. }
  59. }
  60. return fp, nil
  61. }
  62. // MakePathOrDie panics if parts can't be turned into a path. Good for things
  63. // that are known at complie time.
  64. func MakePathOrDie(parts ...interface{}) Path {
  65. fp, err := MakePath(parts...)
  66. if err != nil {
  67. panic(err)
  68. }
  69. return fp
  70. }