-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlists.go
174 lines (141 loc) · 3.26 KB
/
lists.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Code generated by tools/listgen
// DO NOT EDIT!
package graphql
// Errors is a linked list that contains Error values.
type Errors struct {
Data Error
next *Errors
pos int
}
// Add appends a Error to this linked list and returns this new head.
func (es *Errors) Add(data Error) *Errors {
var pos int
if es != nil {
pos = es.pos + 1
}
return &Errors{
Data: data,
next: es,
pos: pos,
}
}
// ForEach applies the given map function to each item in this linked list.
func (es *Errors) ForEach(fn func(e Error, i int)) {
if es == nil {
return
}
iter := 0
current := es
for {
fn(current.Data, iter)
if current.next == nil {
break
}
iter++
current = current.next
}
}
// ErrorsGenerator is a type used to iterate efficiently over Errors.
// @wg:ignore
type ErrorsGenerator struct {
original *Errors
current *Errors
iter int
length int
}
// Next returns the current value, and it's index in the list, and sets up the next value to be
// returned.
func (g *ErrorsGenerator) Next() (Error, int) {
if g.current == nil {
return Error{}, -1
}
retv := g.current.Data
reti := g.iter
g.current = g.current.next
g.iter++
return retv, reti
}
// Reset returns this generator to it's initial state, allowing it to be used again to iterate over
// this linked list.
func (g *ErrorsGenerator) Reset() {
g.current = g.original
g.iter = 0
}
// Generator returns a "Generator" type for this list, allowing for much more efficient iteration
// over items within this linked list than using ForEach, though ForEach may still be more
// convenient, because ForEach is a high order function, it's slower.
func (es *Errors) Generator() ErrorsGenerator {
return ErrorsGenerator{
current: es,
iter: 0,
length: es.Len(),
}
}
// Insert places the Error in the position given by pos.
// The method will insert at top if pos is greater than or equal to list length.
// The method will insert at bottom if the pos is less than 0.
func (es *Errors) Insert(e Error, pos int) *Errors {
if pos >= es.Len() || es == nil {
return es.Add(e)
}
if pos < 0 {
pos = 0
}
mid := es
for mid.pos != pos {
mid = mid.next
}
bot := mid.next
mid.next = nil
es.pos -= mid.pos
bot = bot.Add(e)
es.Join(bot)
return es
}
// Join attaches the tail of the receiver list "es" to the head of the otherList.
func (es *Errors) Join(otherList *Errors) {
if es == nil {
return
}
pos := es.Len() + otherList.Len() - 1
last := es
for es != nil {
es.pos = pos
pos--
last = es
es = es.next
}
last.next = otherList
}
// Len returns the length of this linked list.
func (es *Errors) Len() int {
if es == nil {
return 0
}
return es.pos + 1
}
// Reverse reverses this linked list of Error. Usually when the linked list is being
// constructed the result will be last-to-first, so we'll want to reverse it to get it in the
// "right" order.
func (es *Errors) Reverse() *Errors {
current := es
var prev *Errors
var pos int
for current != nil {
current.pos = pos
pos++
next := current.next
current.next = prev
prev = current
current = next
}
return prev
}
// ErrorsFromSlice returns a Errors list from a slice of Error.
func ErrorsFromSlice(sl []Error) *Errors {
var list *Errors
for _, v := range sl {
list = list.Add(v)
}
return list.Reverse()
}