forked from persiancal/cal-events
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalidate.go
144 lines (118 loc) · 3.09 KB
/
validate.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"fmt"
"regexp"
"strings"
)
var (
partialValidator = regexp.MustCompile("^[a-z0-9_]+$")
multipleSpace = regexp.MustCompile(`\s{2,}`)
)
func refrenceF(a ...interface{}) string {
r := ""
if len(a) == 0 {
return r
}
for i := range a {
r += fmt.Sprintf("%v => ", a[i])
}
return r[:len(r)-3]
}
func textValidator(s string, rs ...interface{}) error {
r := refrenceF(rs)
if strings.TrimSpace(s) != s {
return fmt.Errorf("validate text failed: start and/or end with space in %q", r)
}
if multipleSpace.MatchString(s) {
return fmt.Errorf("validate text failed: double or more white spaces in %q", r)
}
return nil
}
func validate(cmd *command, fl *File) error {
if err := validateEventContent(fl.Events, fl.Months, fl.Countries); err != nil {
return fmt.Errorf("validate events failed: %w", err)
}
if err := validateEventOrder(fl.Events); err != nil {
return fmt.Errorf("validating the events order failed: %w", err)
}
return nil
}
func isValidCountry(c string, list []string) bool {
for i := range list {
if list[i] == c {
return true
}
}
return false
}
func validateEventContent(ev []Event, p *Preset, countries []string) error {
for i := range ev {
if ev[i].Key != 0 {
return fmt.Errorf("the Key should not be in the input file")
}
for l, t := range ev[i].Title {
if err := textValidator(t, ev[i].PartialKey, "title", l); err != nil {
return err
}
}
for l, t := range ev[i].Description {
if err := textValidator(t, ev[i].PartialKey, "description", l); err != nil {
return err
}
}
for l, t := range ev[i].Calendar {
for idx, r := range t {
if err := textValidator(r, ev[i].PartialKey, "calendar", l, idx); err != nil {
return err
}
}
}
for l, t := range ev[i].Holiday {
for p, r := range t {
if err := textValidator(r, ev[i].PartialKey, "holiday", l, p); err != nil {
return err
}
}
}
if !partialValidator.MatchString(ev[i].PartialKey) {
return fmt.Errorf("the partial key %q is invalid, only lower english chars, _ and numbers are allowed ([a-z0-9_])", ev[i].PartialKey)
}
if ev[i].Month <= 0 || ev[i].Month > len(p.MonthsNormal) {
return fmt.Errorf("invalid month on key %d", i)
}
max := p.MonthsNormal[ev[i].Month-1]
if leap := p.MonthsLeap[ev[i].Month-1]; leap > max {
max = leap
}
if ev[i].Day <= 0 || ev[i].Day > max {
return fmt.Errorf("invalid day on key %d", i)
}
for country := range ev[i].Holiday {
if !isValidCountry(country, countries) {
return fmt.Errorf("country is invalid: %q in key %d", country, i)
}
}
}
return nil
}
func validateEventOrder(ev []Event) error {
var (
lastIdx, year int
)
for i := range ev {
if lastIdx > ev[i].idx() {
return fmt.Errorf("the key %d is not in order %+v => %+v", i, ev[i], ev[i-1])
}
if lastIdx == ev[i].idx() {
if ev[i].Year < year {
return fmt.Errorf("the key %q is not in order", ev[i].PartialKey)
}
}
year, lastIdx = ev[i].Year, ev[i].idx()
}
return nil
}
func init() {
cmd := newCommand("validate", "validate the input yaml file", validate)
registerCommand(cmd)
}