1package v4
2
3import (
4	"net/http"
5	"strings"
6)
7
8// validator houses a set of rule needed for validation of a
9// string value
10type rules []rule
11
12// rule interface allows for more flexible rules and just simply
13// checks whether or not a value adheres to that rule
14type rule interface {
15	IsValid(value string) bool
16}
17
18// IsValid will iterate through all rules and see if any rules
19// apply to the value and supports nested rules
20func (r rules) IsValid(value string) bool {
21	for _, rule := range r {
22		if rule.IsValid(value) {
23			return true
24		}
25	}
26	return false
27}
28
29// mapRule generic rule for maps
30type mapRule map[string]struct{}
31
32// IsValid for the map rule satisfies whether it exists in the map
33func (m mapRule) IsValid(value string) bool {
34	_, ok := m[value]
35	return ok
36}
37
38// whitelist is a generic rule for whitelisting
39type whitelist struct {
40	rule
41}
42
43// IsValid for whitelist checks if the value is within the whitelist
44func (w whitelist) IsValid(value string) bool {
45	return w.rule.IsValid(value)
46}
47
48// blacklist is a generic rule for blacklisting
49type blacklist struct {
50	rule
51}
52
53// IsValid for whitelist checks if the value is within the whitelist
54func (b blacklist) IsValid(value string) bool {
55	return !b.rule.IsValid(value)
56}
57
58type patterns []string
59
60// IsValid for patterns checks each pattern and returns if a match has
61// been found
62func (p patterns) IsValid(value string) bool {
63	for _, pattern := range p {
64		if strings.HasPrefix(http.CanonicalHeaderKey(value), pattern) {
65			return true
66		}
67	}
68	return false
69}
70
71// inclusiveRules rules allow for rules to depend on one another
72type inclusiveRules []rule
73
74// IsValid will return true if all rules are true
75func (r inclusiveRules) IsValid(value string) bool {
76	for _, rule := range r {
77		if !rule.IsValid(value) {
78			return false
79		}
80	}
81	return true
82}
83