-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcompiler.go
59 lines (52 loc) · 1.6 KB
/
compiler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package protopath
import (
"context"
"github.com/antlr/antlr4/runtime/Go/antlr"
"github.com/caraml-dev/protopath/parser"
"google.golang.org/protobuf/proto"
)
// Operation responsible to find the value based on compiled jsonpath syntax
type Operation interface {
Lookup(ctx context.Context, obj, rootObj any) (any, error)
}
// Compiled represents operations and way to fetch field based on jsonpath syntax
type Compiled struct {
Operations []Operation
Path string
fieldGetter FieldGetter
}
// NewJsonPathCompiler compile all operations given the jsonpath
func NewJsonPathCompiler(jsonpath string) (*Compiled, error) {
is := antlr.NewInputStream(jsonpath)
lexer := parser.NewJsonPathLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
fieldGetter := &ProtoFieldGetter{}
p := parser.NewJsonPathParser(stream)
visitor := NewJsonPathVisitor(fieldGetter)
allOps, err := visitor.traverseTree(p.Jsonpath(), visitor.operations)
if err != nil {
return nil, err
}
return &Compiled{
Operations: allOps,
Path: jsonpath,
fieldGetter: fieldGetter,
}, nil
}
// Lookup run all the compiled operation based on the jsonpath syntax given proto message obj
// Return of this method not necessary is proto message it can be
// 1. proto.Message
// 2. primitive value
// 3. slice of proto.Message
// 4. slice of pritimive values
func (c *Compiled) Lookup(ctx context.Context, obj proto.Message) (any, error) {
var res any = obj
var err error
for _, op := range c.Operations {
res, err = op.Lookup(ctx, res, obj)
if err != nil {
return nil, err
}
}
return res, nil
}