-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathunion.go
More file actions
90 lines (72 loc) · 1.94 KB
/
union.go
File metadata and controls
90 lines (72 loc) · 1.94 KB
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package vtypes
import (
"context"
"fmt"
"io"
"github.com/Velocidex/ordereddict"
"www.velocidex.com/golang/vfilter"
)
type UnionOptions struct {
Selector *vfilter.Lambda `vfilter:"required,field=selector,doc=A lambda selector"`
Choices *ordereddict.Dict `vfilter:"required,field=choices,doc=A between values and strings"`
choices map[string]Parser
}
type Union struct {
options UnionOptions
profile *Profile
}
func (self *Union) New(profile *Profile, options *ordereddict.Dict) (Parser, error) {
if options == nil {
return nil, fmt.Errorf("Union parser requires options")
}
result := &Union{profile: profile}
ctx := context.Background()
err := ParseOptions(ctx, options, &result.options)
if err != nil {
return nil, fmt.Errorf("Union: %w", err)
}
return result, nil
}
func (self *Union) Parse(
scope vfilter.Scope, reader io.ReaderAt, offset int64) interface{} {
var value interface{}
// Initialize the choices late to ensure they are all defined by
// now.
if self.options.choices == nil {
self.options.choices = make(map[string]Parser)
for _, k := range self.options.Choices.Keys() {
parser_name, pres := self.options.Choices.GetString(k)
if !pres {
continue
}
parser, err := self.profile.GetParser(
parser_name, ordereddict.NewDict())
if err != nil {
scope.Log("ERROR:binary_parser: Union: %v", err)
} else {
self.options.choices[k] = parser
}
}
}
subscope := scope.Copy()
defer subscope.Close()
this_obj, pres := getThis(subscope)
if pres {
value = self.options.Selector.Reduce(
context.Background(), subscope, []vfilter.Any{this_obj})
}
if IsNil(value) {
return &vfilter.Null{}
}
value_str := fmt.Sprintf("%v", value)
parser, pres := self.options.choices[value_str]
if pres {
return parser.Parse(scope, reader, offset)
}
// Try the default
parser, pres = self.options.choices["default"]
if pres {
return parser.Parse(scope, reader, offset)
}
return &vfilter.Null{}
}