...
1 package ast
2
3 import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 )
8
9 var _ json.Unmarshaler = (*Path)(nil)
10
11 type Path []PathElement
12
13 type PathElement interface {
14 isPathElement()
15 }
16
17 var _ PathElement = PathIndex(0)
18 var _ PathElement = PathName("")
19
20 func (path Path) String() string {
21 if path == nil {
22 return ""
23 }
24 var str bytes.Buffer
25 for i, v := range path {
26 switch v := v.(type) {
27 case PathIndex:
28 str.WriteString(fmt.Sprintf("[%d]", v))
29 case PathName:
30 if i != 0 {
31 str.WriteByte('.')
32 }
33 str.WriteString(string(v))
34 default:
35 panic(fmt.Sprintf("unknown type: %T", v))
36 }
37 }
38 return str.String()
39 }
40
41 func (path *Path) UnmarshalJSON(b []byte) error {
42 var vs []interface{}
43 err := json.Unmarshal(b, &vs)
44 if err != nil {
45 return err
46 }
47
48 *path = make([]PathElement, 0, len(vs))
49 for _, v := range vs {
50 switch v := v.(type) {
51 case string:
52 *path = append(*path, PathName(v))
53 case int:
54 *path = append(*path, PathIndex(v))
55 case float64:
56 *path = append(*path, PathIndex(int(v)))
57 default:
58 return fmt.Errorf("unknown path element type: %T", v)
59 }
60 }
61 return nil
62 }
63
64 type PathIndex int
65
66 func (PathIndex) isPathElement() {}
67
68 type PathName string
69
70 func (PathName) isPathElement() {}
71
View as plain text