-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.go
77 lines (69 loc) · 1.74 KB
/
parser.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package router
import (
"fmt"
"strings"
"github.com/pkg/errors"
)
const (
defaultCloudFrontNumColumns = 33
)
// recordParser predefined errors
var (
SkipLine = errors.New("Please skip this line.")
)
type recordParserFunc func([]byte) ([]*record, error)
func (p recordParserFunc) Parse(bs []byte) ([]*record, error) {
return p(bs)
}
type cloudfrontParser struct {
version string
fields []string
}
func (p *cloudfrontParser) Parse(bs []byte) ([]*record, error) {
str := string(bs)
rec := newRecord(bs)
if str[0] == '#' {
part := strings.SplitN(str[1:], ":", 2)
if len(part) != 2 {
return nil, SkipLine
}
key := strings.TrimSpace(part[0])
value := strings.TrimSpace(part[1])
switch key {
case "Version":
p.version = value
case "Fields":
rawFields := strings.Split(value, " ")
//convert to snake case
fields := make([]string, 0, len(rawFields))
replaceTargets := []string{"(", ")", "-"}
for _, rawField := range rawFields {
field := rawField
for _, target := range replaceTargets {
field = strings.ReplaceAll(field, target, "_")
}
field = strings.ToLower(field)
field = strings.TrimRight(field, "_")
fields = append(fields, field)
}
p.fields = fields
}
return nil, SkipLine
}
values := strings.Split(str, "\t")
if len(values) > len(p.fields) {
return nil, fmt.Errorf("this row has more values than fields, num of values = %d, num of feilds = %d", len(values), len(p.fields))
}
var dateValue, timeValue string
for i, field := range p.fields {
rec.parsed[field] = values[i]
if field == "date" {
dateValue = values[i]
}
if field == "time" {
timeValue = values[i]
}
}
rec.parsed["datetime"] = dateValue + "T" + timeValue + "Z"
return []*record{rec}, nil
}