Test Failed
Pull Request — main (#74)
by Igor
01:48
created

validation.ArrayIndexElement.String   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
dl 0
loc 2
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
nop 0
1
package validation
2
3
import (
4
	"encoding/json"
5
	"fmt"
6
	"strconv"
7
)
8
9
// PropertyPathElement is a part of the PropertyPath.
10
type PropertyPathElement interface {
11
	// IsIndex can be used to determine whether an element is a string (property name) or
12
	// an index array.
13
	IsIndex() bool
14
	fmt.Stringer
15
}
16
17
// PropertyName holds up property name value under PropertyPath.
18
type PropertyName string
19
20
// IsIndex on PropertyName always returns false.
21
func (p PropertyName) IsIndex() bool {
22 1
	return false
23
}
24
25
// String returns property name as is.
26
func (p PropertyName) String() string {
27 1
	return string(p)
28
}
29
30
// ArrayIndex holds up array index value under PropertyPath.
31
type ArrayIndex int
32
33
// IsIndex on ArrayIndex always returns true.
34
func (a ArrayIndex) IsIndex() bool {
35 1
	return true
36
}
37
38
// String returns array index values converted into a string.
39
func (a ArrayIndex) String() string {
40 1
	return strconv.Itoa(int(a))
41
}
42
43
// PropertyPath is generated by the validator and indicates how it reached the invalid value
44
// from the root element. Property path is denoted by dots, while array access
45
// is denoted by square brackets. For example, "book.keywords[0]" means that the violation
46
// occurred on the first element of array "keywords" in the "book" object.
47
//
48
// Internally PropertyPath is a linked list. You can create a new path using WithProperty
49
// or WithIndex methods. PropertyPath should always be used as a pointer value.
50
// Nil value is a valid value that means that the property path is empty.
51
type PropertyPath struct {
52
	parent *PropertyPath
53
	value  PropertyPathElement
54
}
55
56
// NewPropertyPath creates a PropertyPath from the list of elements. If the list is empty nil will be returned.
57
// Nil value is a valid value that means that the property path is empty.
58
func NewPropertyPath(elements ...PropertyPathElement) *PropertyPath {
59 1
	var path *PropertyPath
60 1
61 1
	return path.With(elements...)
62
}
63 1
64
// With returns new PropertyPath with appended elements to the end of the list.
65
func (path *PropertyPath) With(elements ...PropertyPathElement) *PropertyPath {
66
	current := path
67
	for _, element := range elements {
68 1
		current = &PropertyPath{parent: current, value: element}
69
	}
70
71
	return current
72
}
73
74
// WithProperty returns new PropertyPath with appended PropertyName to the end of the list.
75
func (path *PropertyPath) WithProperty(name string) *PropertyPath {
76 1
	return &PropertyPath{
77
		parent: path,
78
		value:  PropertyName(name),
79
	}
80
}
81
82
// WithIndex returns new PropertyPath with appended ArrayIndex to the end of the list.
83
func (path *PropertyPath) WithIndex(index int) *PropertyPath {
84 1
	return &PropertyPath{
85 1
		parent: path,
86 1
		value:  ArrayIndex(index),
87 1
	}
88 1
}
89
90 1
// String is used to format property path to a string.
91 1
func (path *PropertyPath) String() string {
92 1
	s := ""
93
	element := path
94
	for element != nil {
95 1
		if element.value.IsIndex() {
96
			s = "[" + element.value.String() + "]" + s
97
		} else {
98 1
			s = element.value.String() + s
99
			if element.parent != nil {
100
				s = "." + s
101
			}
102
		}
103 1
		element = element.parent
104
	}
105
106
	return s
107
}
108
109
// MarshalJSON will marshal property path value to a JSON string.
110
func (path *PropertyPath) MarshalJSON() ([]byte, error) {
111
	return json.Marshal(path.String())
112
}
113