Bladeren bron

Add vendor/

Thomas Frössman 9 jaren geleden
bovenliggende
commit
048555dbaa
40 gewijzigde bestanden met toevoegingen van 20223 en 0 verwijderingen
  1. 151
    0
      vendor/github.com/davecgh/go-spew/spew/bypass.go
  2. 37
    0
      vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
  3. 341
    0
      vendor/github.com/davecgh/go-spew/spew/common.go
  4. 297
    0
      vendor/github.com/davecgh/go-spew/spew/config.go
  5. 202
    0
      vendor/github.com/davecgh/go-spew/spew/doc.go
  6. 509
    0
      vendor/github.com/davecgh/go-spew/spew/dump.go
  7. 419
    0
      vendor/github.com/davecgh/go-spew/spew/format.go
  8. 148
    0
      vendor/github.com/davecgh/go-spew/spew/spew.go
  9. 54
    0
      vendor/github.com/garyburd/redigo/internal/commandinfo.go
  10. 567
    0
      vendor/github.com/garyburd/redigo/redis/conn.go
  11. 169
    0
      vendor/github.com/garyburd/redigo/redis/doc.go
  12. 117
    0
      vendor/github.com/garyburd/redigo/redis/log.go
  13. 393
    0
      vendor/github.com/garyburd/redigo/redis/pool.go
  14. 144
    0
      vendor/github.com/garyburd/redigo/redis/pubsub.go
  15. 44
    0
      vendor/github.com/garyburd/redigo/redis/redis.go
  16. 393
    0
      vendor/github.com/garyburd/redigo/redis/reply.go
  17. 555
    0
      vendor/github.com/garyburd/redigo/redis/scan.go
  18. 86
    0
      vendor/github.com/garyburd/redigo/redis/script.go
  19. 6372
    0
      vendor/github.com/osrg/gobgp/packet/bgp.go
  20. 28
    0
      vendor/github.com/osrg/gobgp/packet/bgpattrtype_string.go
  21. 40
    0
      vendor/github.com/osrg/gobgp/packet/bgpcapabilitycode_string.go
  22. 609
    0
      vendor/github.com/osrg/gobgp/packet/bmp.go
  23. 133
    0
      vendor/github.com/osrg/gobgp/packet/constant.go
  24. 16
    0
      vendor/github.com/osrg/gobgp/packet/esitype_string.go
  25. 16
    0
      vendor/github.com/osrg/gobgp/packet/fsmstate_string.go
  26. 798
    0
      vendor/github.com/osrg/gobgp/packet/mrt.go
  27. 63
    0
      vendor/github.com/osrg/gobgp/packet/routefamily_string.go
  28. 392
    0
      vendor/github.com/osrg/gobgp/packet/rtr.go
  29. 221
    0
      vendor/github.com/osrg/gobgp/packet/validate.go
  30. 102
    0
      vendor/golang.org/x/net/html/const.go
  31. 106
    0
      vendor/golang.org/x/net/html/doc.go
  32. 156
    0
      vendor/golang.org/x/net/html/doctype.go
  33. 2253
    0
      vendor/golang.org/x/net/html/entity.go
  34. 258
    0
      vendor/golang.org/x/net/html/escape.go
  35. 226
    0
      vendor/golang.org/x/net/html/foreign.go
  36. 193
    0
      vendor/golang.org/x/net/html/node.go
  37. 2094
    0
      vendor/golang.org/x/net/html/parse.go
  38. 271
    0
      vendor/golang.org/x/net/html/render.go
  39. 1219
    0
      vendor/golang.org/x/net/html/token.go
  40. 31
    0
      vendor/vendor.json

+ 151
- 0
vendor/github.com/davecgh/go-spew/spew/bypass.go Bestand weergeven

@@ -0,0 +1,151 @@
1
+// Copyright (c) 2015 Dave Collins <dave@davec.name>
2
+//
3
+// Permission to use, copy, modify, and distribute this software for any
4
+// purpose with or without fee is hereby granted, provided that the above
5
+// copyright notice and this permission notice appear in all copies.
6
+//
7
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
+
15
+// NOTE: Due to the following build constraints, this file will only be compiled
16
+// when the code is not running on Google App Engine and "-tags disableunsafe"
17
+// is not added to the go build command line.
18
+// +build !appengine,!disableunsafe
19
+
20
+package spew
21
+
22
+import (
23
+	"reflect"
24
+	"unsafe"
25
+)
26
+
27
+const (
28
+	// UnsafeDisabled is a build-time constant which specifies whether or
29
+	// not access to the unsafe package is available.
30
+	UnsafeDisabled = false
31
+
32
+	// ptrSize is the size of a pointer on the current arch.
33
+	ptrSize = unsafe.Sizeof((*byte)(nil))
34
+)
35
+
36
+var (
37
+	// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
38
+	// internal reflect.Value fields.  These values are valid before golang
39
+	// commit ecccf07e7f9d which changed the format.  The are also valid
40
+	// after commit 82f48826c6c7 which changed the format again to mirror
41
+	// the original format.  Code in the init function updates these offsets
42
+	// as necessary.
43
+	offsetPtr    = uintptr(ptrSize)
44
+	offsetScalar = uintptr(0)
45
+	offsetFlag   = uintptr(ptrSize * 2)
46
+
47
+	// flagKindWidth and flagKindShift indicate various bits that the
48
+	// reflect package uses internally to track kind information.
49
+	//
50
+	// flagRO indicates whether or not the value field of a reflect.Value is
51
+	// read-only.
52
+	//
53
+	// flagIndir indicates whether the value field of a reflect.Value is
54
+	// the actual data or a pointer to the data.
55
+	//
56
+	// These values are valid before golang commit 90a7c3c86944 which
57
+	// changed their positions.  Code in the init function updates these
58
+	// flags as necessary.
59
+	flagKindWidth = uintptr(5)
60
+	flagKindShift = uintptr(flagKindWidth - 1)
61
+	flagRO        = uintptr(1 << 0)
62
+	flagIndir     = uintptr(1 << 1)
63
+)
64
+
65
+func init() {
66
+	// Older versions of reflect.Value stored small integers directly in the
67
+	// ptr field (which is named val in the older versions).  Versions
68
+	// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
69
+	// scalar for this purpose which unfortunately came before the flag
70
+	// field, so the offset of the flag field is different for those
71
+	// versions.
72
+	//
73
+	// This code constructs a new reflect.Value from a known small integer
74
+	// and checks if the size of the reflect.Value struct indicates it has
75
+	// the scalar field. When it does, the offsets are updated accordingly.
76
+	vv := reflect.ValueOf(0xf00)
77
+	if unsafe.Sizeof(vv) == (ptrSize * 4) {
78
+		offsetScalar = ptrSize * 2
79
+		offsetFlag = ptrSize * 3
80
+	}
81
+
82
+	// Commit 90a7c3c86944 changed the flag positions such that the low
83
+	// order bits are the kind.  This code extracts the kind from the flags
84
+	// field and ensures it's the correct type.  When it's not, the flag
85
+	// order has been changed to the newer format, so the flags are updated
86
+	// accordingly.
87
+	upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
88
+	upfv := *(*uintptr)(upf)
89
+	flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
90
+	if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
91
+		flagKindShift = 0
92
+		flagRO = 1 << 5
93
+		flagIndir = 1 << 6
94
+
95
+		// Commit adf9b30e5594 modified the flags to separate the
96
+		// flagRO flag into two bits which specifies whether or not the
97
+		// field is embedded.  This causes flagIndir to move over a bit
98
+		// and means that flagRO is the combination of either of the
99
+		// original flagRO bit and the new bit.
100
+		//
101
+		// This code detects the change by extracting what used to be
102
+		// the indirect bit to ensure it's set.  When it's not, the flag
103
+		// order has been changed to the newer format, so the flags are
104
+		// updated accordingly.
105
+		if upfv&flagIndir == 0 {
106
+			flagRO = 3 << 5
107
+			flagIndir = 1 << 7
108
+		}
109
+	}
110
+}
111
+
112
+// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
113
+// the typical safety restrictions preventing access to unaddressable and
114
+// unexported data.  It works by digging the raw pointer to the underlying
115
+// value out of the protected value and generating a new unprotected (unsafe)
116
+// reflect.Value to it.
117
+//
118
+// This allows us to check for implementations of the Stringer and error
119
+// interfaces to be used for pretty printing ordinarily unaddressable and
120
+// inaccessible values such as unexported struct fields.
121
+func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
122
+	indirects := 1
123
+	vt := v.Type()
124
+	upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
125
+	rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
126
+	if rvf&flagIndir != 0 {
127
+		vt = reflect.PtrTo(v.Type())
128
+		indirects++
129
+	} else if offsetScalar != 0 {
130
+		// The value is in the scalar field when it's not one of the
131
+		// reference types.
132
+		switch vt.Kind() {
133
+		case reflect.Uintptr:
134
+		case reflect.Chan:
135
+		case reflect.Func:
136
+		case reflect.Map:
137
+		case reflect.Ptr:
138
+		case reflect.UnsafePointer:
139
+		default:
140
+			upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
141
+				offsetScalar)
142
+		}
143
+	}
144
+
145
+	pv := reflect.NewAt(vt, upv)
146
+	rv = pv
147
+	for i := 0; i < indirects; i++ {
148
+		rv = rv.Elem()
149
+	}
150
+	return rv
151
+}

+ 37
- 0
vendor/github.com/davecgh/go-spew/spew/bypasssafe.go Bestand weergeven

@@ -0,0 +1,37 @@
1
+// Copyright (c) 2015 Dave Collins <dave@davec.name>
2
+//
3
+// Permission to use, copy, modify, and distribute this software for any
4
+// purpose with or without fee is hereby granted, provided that the above
5
+// copyright notice and this permission notice appear in all copies.
6
+//
7
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
+
15
+// NOTE: Due to the following build constraints, this file will only be compiled
16
+// when either the code is running on Google App Engine or "-tags disableunsafe"
17
+// is added to the go build command line.
18
+// +build appengine disableunsafe
19
+
20
+package spew
21
+
22
+import "reflect"
23
+
24
+const (
25
+	// UnsafeDisabled is a build-time constant which specifies whether or
26
+	// not access to the unsafe package is available.
27
+	UnsafeDisabled = true
28
+)
29
+
30
+// unsafeReflectValue typically converts the passed reflect.Value into a one
31
+// that bypasses the typical safety restrictions preventing access to
32
+// unaddressable and unexported data.  However, doing this relies on access to
33
+// the unsafe package.  This is a stub version which simply returns the passed
34
+// reflect.Value when the unsafe package is not available.
35
+func unsafeReflectValue(v reflect.Value) reflect.Value {
36
+	return v
37
+}

+ 341
- 0
vendor/github.com/davecgh/go-spew/spew/common.go Bestand weergeven

@@ -0,0 +1,341 @@
1
+/*
2
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+package spew
18
+
19
+import (
20
+	"bytes"
21
+	"fmt"
22
+	"io"
23
+	"reflect"
24
+	"sort"
25
+	"strconv"
26
+)
27
+
28
+// Some constants in the form of bytes to avoid string overhead.  This mirrors
29
+// the technique used in the fmt package.
30
+var (
31
+	panicBytes            = []byte("(PANIC=")
32
+	plusBytes             = []byte("+")
33
+	iBytes                = []byte("i")
34
+	trueBytes             = []byte("true")
35
+	falseBytes            = []byte("false")
36
+	interfaceBytes        = []byte("(interface {})")
37
+	commaNewlineBytes     = []byte(",\n")
38
+	newlineBytes          = []byte("\n")
39
+	openBraceBytes        = []byte("{")
40
+	openBraceNewlineBytes = []byte("{\n")
41
+	closeBraceBytes       = []byte("}")
42
+	asteriskBytes         = []byte("*")
43
+	colonBytes            = []byte(":")
44
+	colonSpaceBytes       = []byte(": ")
45
+	openParenBytes        = []byte("(")
46
+	closeParenBytes       = []byte(")")
47
+	spaceBytes            = []byte(" ")
48
+	pointerChainBytes     = []byte("->")
49
+	nilAngleBytes         = []byte("<nil>")
50
+	maxNewlineBytes       = []byte("<max depth reached>\n")
51
+	maxShortBytes         = []byte("<max>")
52
+	circularBytes         = []byte("<already shown>")
53
+	circularShortBytes    = []byte("<shown>")
54
+	invalidAngleBytes     = []byte("<invalid>")
55
+	openBracketBytes      = []byte("[")
56
+	closeBracketBytes     = []byte("]")
57
+	percentBytes          = []byte("%")
58
+	precisionBytes        = []byte(".")
59
+	openAngleBytes        = []byte("<")
60
+	closeAngleBytes       = []byte(">")
61
+	openMapBytes          = []byte("map[")
62
+	closeMapBytes         = []byte("]")
63
+	lenEqualsBytes        = []byte("len=")
64
+	capEqualsBytes        = []byte("cap=")
65
+)
66
+
67
+// hexDigits is used to map a decimal value to a hex digit.
68
+var hexDigits = "0123456789abcdef"
69
+
70
+// catchPanic handles any panics that might occur during the handleMethods
71
+// calls.
72
+func catchPanic(w io.Writer, v reflect.Value) {
73
+	if err := recover(); err != nil {
74
+		w.Write(panicBytes)
75
+		fmt.Fprintf(w, "%v", err)
76
+		w.Write(closeParenBytes)
77
+	}
78
+}
79
+
80
+// handleMethods attempts to call the Error and String methods on the underlying
81
+// type the passed reflect.Value represents and outputes the result to Writer w.
82
+//
83
+// It handles panics in any called methods by catching and displaying the error
84
+// as the formatted value.
85
+func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
86
+	// We need an interface to check if the type implements the error or
87
+	// Stringer interface.  However, the reflect package won't give us an
88
+	// interface on certain things like unexported struct fields in order
89
+	// to enforce visibility rules.  We use unsafe, when it's available,
90
+	// to bypass these restrictions since this package does not mutate the
91
+	// values.
92
+	if !v.CanInterface() {
93
+		if UnsafeDisabled {
94
+			return false
95
+		}
96
+
97
+		v = unsafeReflectValue(v)
98
+	}
99
+
100
+	// Choose whether or not to do error and Stringer interface lookups against
101
+	// the base type or a pointer to the base type depending on settings.
102
+	// Technically calling one of these methods with a pointer receiver can
103
+	// mutate the value, however, types which choose to satisify an error or
104
+	// Stringer interface with a pointer receiver should not be mutating their
105
+	// state inside these interface methods.
106
+	if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
107
+		v = unsafeReflectValue(v)
108
+	}
109
+	if v.CanAddr() {
110
+		v = v.Addr()
111
+	}
112
+
113
+	// Is it an error or Stringer?
114
+	switch iface := v.Interface().(type) {
115
+	case error:
116
+		defer catchPanic(w, v)
117
+		if cs.ContinueOnMethod {
118
+			w.Write(openParenBytes)
119
+			w.Write([]byte(iface.Error()))
120
+			w.Write(closeParenBytes)
121
+			w.Write(spaceBytes)
122
+			return false
123
+		}
124
+
125
+		w.Write([]byte(iface.Error()))
126
+		return true
127
+
128
+	case fmt.Stringer:
129
+		defer catchPanic(w, v)
130
+		if cs.ContinueOnMethod {
131
+			w.Write(openParenBytes)
132
+			w.Write([]byte(iface.String()))
133
+			w.Write(closeParenBytes)
134
+			w.Write(spaceBytes)
135
+			return false
136
+		}
137
+		w.Write([]byte(iface.String()))
138
+		return true
139
+	}
140
+	return false
141
+}
142
+
143
+// printBool outputs a boolean value as true or false to Writer w.
144
+func printBool(w io.Writer, val bool) {
145
+	if val {
146
+		w.Write(trueBytes)
147
+	} else {
148
+		w.Write(falseBytes)
149
+	}
150
+}
151
+
152
+// printInt outputs a signed integer value to Writer w.
153
+func printInt(w io.Writer, val int64, base int) {
154
+	w.Write([]byte(strconv.FormatInt(val, base)))
155
+}
156
+
157
+// printUint outputs an unsigned integer value to Writer w.
158
+func printUint(w io.Writer, val uint64, base int) {
159
+	w.Write([]byte(strconv.FormatUint(val, base)))
160
+}
161
+
162
+// printFloat outputs a floating point value using the specified precision,
163
+// which is expected to be 32 or 64bit, to Writer w.
164
+func printFloat(w io.Writer, val float64, precision int) {
165
+	w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
166
+}
167
+
168
+// printComplex outputs a complex value using the specified float precision
169
+// for the real and imaginary parts to Writer w.
170
+func printComplex(w io.Writer, c complex128, floatPrecision int) {
171
+	r := real(c)
172
+	w.Write(openParenBytes)
173
+	w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
174
+	i := imag(c)
175
+	if i >= 0 {
176
+		w.Write(plusBytes)
177
+	}
178
+	w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
179
+	w.Write(iBytes)
180
+	w.Write(closeParenBytes)
181
+}
182
+
183
+// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
184
+// prefix to Writer w.
185
+func printHexPtr(w io.Writer, p uintptr) {
186
+	// Null pointer.
187
+	num := uint64(p)
188
+	if num == 0 {
189
+		w.Write(nilAngleBytes)
190
+		return
191
+	}
192
+
193
+	// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
194
+	buf := make([]byte, 18)
195
+
196
+	// It's simpler to construct the hex string right to left.
197
+	base := uint64(16)
198
+	i := len(buf) - 1
199
+	for num >= base {
200
+		buf[i] = hexDigits[num%base]
201
+		num /= base
202
+		i--
203
+	}
204
+	buf[i] = hexDigits[num]
205
+
206
+	// Add '0x' prefix.
207
+	i--
208
+	buf[i] = 'x'
209
+	i--
210
+	buf[i] = '0'
211
+
212
+	// Strip unused leading bytes.
213
+	buf = buf[i:]
214
+	w.Write(buf)
215
+}
216
+
217
+// valuesSorter implements sort.Interface to allow a slice of reflect.Value
218
+// elements to be sorted.
219
+type valuesSorter struct {
220
+	values  []reflect.Value
221
+	strings []string // either nil or same len and values
222
+	cs      *ConfigState
223
+}
224
+
225
+// newValuesSorter initializes a valuesSorter instance, which holds a set of
226
+// surrogate keys on which the data should be sorted.  It uses flags in
227
+// ConfigState to decide if and how to populate those surrogate keys.
228
+func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
229
+	vs := &valuesSorter{values: values, cs: cs}
230
+	if canSortSimply(vs.values[0].Kind()) {
231
+		return vs
232
+	}
233
+	if !cs.DisableMethods {
234
+		vs.strings = make([]string, len(values))
235
+		for i := range vs.values {
236
+			b := bytes.Buffer{}
237
+			if !handleMethods(cs, &b, vs.values[i]) {
238
+				vs.strings = nil
239
+				break
240
+			}
241
+			vs.strings[i] = b.String()
242
+		}
243
+	}
244
+	if vs.strings == nil && cs.SpewKeys {
245
+		vs.strings = make([]string, len(values))
246
+		for i := range vs.values {
247
+			vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
248
+		}
249
+	}
250
+	return vs
251
+}
252
+
253
+// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
254
+// directly, or whether it should be considered for sorting by surrogate keys
255
+// (if the ConfigState allows it).
256
+func canSortSimply(kind reflect.Kind) bool {
257
+	// This switch parallels valueSortLess, except for the default case.
258
+	switch kind {
259
+	case reflect.Bool:
260
+		return true
261
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
262
+		return true
263
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
264
+		return true
265
+	case reflect.Float32, reflect.Float64:
266
+		return true
267
+	case reflect.String:
268
+		return true
269
+	case reflect.Uintptr:
270
+		return true
271
+	case reflect.Array:
272
+		return true
273
+	}
274
+	return false
275
+}
276
+
277
+// Len returns the number of values in the slice.  It is part of the
278
+// sort.Interface implementation.
279
+func (s *valuesSorter) Len() int {
280
+	return len(s.values)
281
+}
282
+
283
+// Swap swaps the values at the passed indices.  It is part of the
284
+// sort.Interface implementation.
285
+func (s *valuesSorter) Swap(i, j int) {
286
+	s.values[i], s.values[j] = s.values[j], s.values[i]
287
+	if s.strings != nil {
288
+		s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
289
+	}
290
+}
291
+
292
+// valueSortLess returns whether the first value should sort before the second
293
+// value.  It is used by valueSorter.Less as part of the sort.Interface
294
+// implementation.
295
+func valueSortLess(a, b reflect.Value) bool {
296
+	switch a.Kind() {
297
+	case reflect.Bool:
298
+		return !a.Bool() && b.Bool()
299
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
300
+		return a.Int() < b.Int()
301
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
302
+		return a.Uint() < b.Uint()
303
+	case reflect.Float32, reflect.Float64:
304
+		return a.Float() < b.Float()
305
+	case reflect.String:
306
+		return a.String() < b.String()
307
+	case reflect.Uintptr:
308
+		return a.Uint() < b.Uint()
309
+	case reflect.Array:
310
+		// Compare the contents of both arrays.
311
+		l := a.Len()
312
+		for i := 0; i < l; i++ {
313
+			av := a.Index(i)
314
+			bv := b.Index(i)
315
+			if av.Interface() == bv.Interface() {
316
+				continue
317
+			}
318
+			return valueSortLess(av, bv)
319
+		}
320
+	}
321
+	return a.String() < b.String()
322
+}
323
+
324
+// Less returns whether the value at index i should sort before the
325
+// value at index j.  It is part of the sort.Interface implementation.
326
+func (s *valuesSorter) Less(i, j int) bool {
327
+	if s.strings == nil {
328
+		return valueSortLess(s.values[i], s.values[j])
329
+	}
330
+	return s.strings[i] < s.strings[j]
331
+}
332
+
333
+// sortValues is a sort function that handles both native types and any type that
334
+// can be converted to error or Stringer.  Other inputs are sorted according to
335
+// their Value.String() value to ensure display stability.
336
+func sortValues(values []reflect.Value, cs *ConfigState) {
337
+	if len(values) == 0 {
338
+		return
339
+	}
340
+	sort.Sort(newValuesSorter(values, cs))
341
+}

+ 297
- 0
vendor/github.com/davecgh/go-spew/spew/config.go Bestand weergeven

@@ -0,0 +1,297 @@
1
+/*
2
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+package spew
18
+
19
+import (
20
+	"bytes"
21
+	"fmt"
22
+	"io"
23
+	"os"
24
+)
25
+
26
+// ConfigState houses the configuration options used by spew to format and
27
+// display values.  There is a global instance, Config, that is used to control
28
+// all top-level Formatter and Dump functionality.  Each ConfigState instance
29
+// provides methods equivalent to the top-level functions.
30
+//
31
+// The zero value for ConfigState provides no indentation.  You would typically
32
+// want to set it to a space or a tab.
33
+//
34
+// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
35
+// with default settings.  See the documentation of NewDefaultConfig for default
36
+// values.
37
+type ConfigState struct {
38
+	// Indent specifies the string to use for each indentation level.  The
39
+	// global config instance that all top-level functions use set this to a
40
+	// single space by default.  If you would like more indentation, you might
41
+	// set this to a tab with "\t" or perhaps two spaces with "  ".
42
+	Indent string
43
+
44
+	// MaxDepth controls the maximum number of levels to descend into nested
45
+	// data structures.  The default, 0, means there is no limit.
46
+	//
47
+	// NOTE: Circular data structures are properly detected, so it is not
48
+	// necessary to set this value unless you specifically want to limit deeply
49
+	// nested data structures.
50
+	MaxDepth int
51
+
52
+	// DisableMethods specifies whether or not error and Stringer interfaces are
53
+	// invoked for types that implement them.
54
+	DisableMethods bool
55
+
56
+	// DisablePointerMethods specifies whether or not to check for and invoke
57
+	// error and Stringer interfaces on types which only accept a pointer
58
+	// receiver when the current type is not a pointer.
59
+	//
60
+	// NOTE: This might be an unsafe action since calling one of these methods
61
+	// with a pointer receiver could technically mutate the value, however,
62
+	// in practice, types which choose to satisify an error or Stringer
63
+	// interface with a pointer receiver should not be mutating their state
64
+	// inside these interface methods.  As a result, this option relies on
65
+	// access to the unsafe package, so it will not have any effect when
66
+	// running in environments without access to the unsafe package such as
67
+	// Google App Engine or with the "disableunsafe" build tag specified.
68
+	DisablePointerMethods bool
69
+
70
+	// ContinueOnMethod specifies whether or not recursion should continue once
71
+	// a custom error or Stringer interface is invoked.  The default, false,
72
+	// means it will print the results of invoking the custom error or Stringer
73
+	// interface and return immediately instead of continuing to recurse into
74
+	// the internals of the data type.
75
+	//
76
+	// NOTE: This flag does not have any effect if method invocation is disabled
77
+	// via the DisableMethods or DisablePointerMethods options.
78
+	ContinueOnMethod bool
79
+
80
+	// SortKeys specifies map keys should be sorted before being printed. Use
81
+	// this to have a more deterministic, diffable output.  Note that only
82
+	// native types (bool, int, uint, floats, uintptr and string) and types
83
+	// that support the error or Stringer interfaces (if methods are
84
+	// enabled) are supported, with other types sorted according to the
85
+	// reflect.Value.String() output which guarantees display stability.
86
+	SortKeys bool
87
+
88
+	// SpewKeys specifies that, as a last resort attempt, map keys should
89
+	// be spewed to strings and sorted by those strings.  This is only
90
+	// considered if SortKeys is true.
91
+	SpewKeys bool
92
+}
93
+
94
+// Config is the active configuration of the top-level functions.
95
+// The configuration can be changed by modifying the contents of spew.Config.
96
+var Config = ConfigState{Indent: " "}
97
+
98
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
99
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
100
+// the formatted string as a value that satisfies error.  See NewFormatter
101
+// for formatting details.
102
+//
103
+// This function is shorthand for the following syntax:
104
+//
105
+//	fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
106
+func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
107
+	return fmt.Errorf(format, c.convertArgs(a)...)
108
+}
109
+
110
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
111
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
112
+// the number of bytes written and any write error encountered.  See
113
+// NewFormatter for formatting details.
114
+//
115
+// This function is shorthand for the following syntax:
116
+//
117
+//	fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
118
+func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
119
+	return fmt.Fprint(w, c.convertArgs(a)...)
120
+}
121
+
122
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
123
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
124
+// the number of bytes written and any write error encountered.  See
125
+// NewFormatter for formatting details.
126
+//
127
+// This function is shorthand for the following syntax:
128
+//
129
+//	fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
130
+func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
131
+	return fmt.Fprintf(w, format, c.convertArgs(a)...)
132
+}
133
+
134
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
135
+// passed with a Formatter interface returned by c.NewFormatter.  See
136
+// NewFormatter for formatting details.
137
+//
138
+// This function is shorthand for the following syntax:
139
+//
140
+//	fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
141
+func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
142
+	return fmt.Fprintln(w, c.convertArgs(a)...)
143
+}
144
+
145
+// Print is a wrapper for fmt.Print that treats each argument as if it were
146
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
147
+// the number of bytes written and any write error encountered.  See
148
+// NewFormatter for formatting details.
149
+//
150
+// This function is shorthand for the following syntax:
151
+//
152
+//	fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
153
+func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
154
+	return fmt.Print(c.convertArgs(a)...)
155
+}
156
+
157
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
158
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
159
+// the number of bytes written and any write error encountered.  See
160
+// NewFormatter for formatting details.
161
+//
162
+// This function is shorthand for the following syntax:
163
+//
164
+//	fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
165
+func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
166
+	return fmt.Printf(format, c.convertArgs(a)...)
167
+}
168
+
169
+// Println is a wrapper for fmt.Println that treats each argument as if it were
170
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
171
+// the number of bytes written and any write error encountered.  See
172
+// NewFormatter for formatting details.
173
+//
174
+// This function is shorthand for the following syntax:
175
+//
176
+//	fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
177
+func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
178
+	return fmt.Println(c.convertArgs(a)...)
179
+}
180
+
181
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
182
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
183
+// the resulting string.  See NewFormatter for formatting details.
184
+//
185
+// This function is shorthand for the following syntax:
186
+//
187
+//	fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
188
+func (c *ConfigState) Sprint(a ...interface{}) string {
189
+	return fmt.Sprint(c.convertArgs(a)...)
190
+}
191
+
192
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
193
+// passed with a Formatter interface returned by c.NewFormatter.  It returns
194
+// the resulting string.  See NewFormatter for formatting details.
195
+//
196
+// This function is shorthand for the following syntax:
197
+//
198
+//	fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
199
+func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
200
+	return fmt.Sprintf(format, c.convertArgs(a)...)
201
+}
202
+
203
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
204
+// were passed with a Formatter interface returned by c.NewFormatter.  It
205
+// returns the resulting string.  See NewFormatter for formatting details.
206
+//
207
+// This function is shorthand for the following syntax:
208
+//
209
+//	fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
210
+func (c *ConfigState) Sprintln(a ...interface{}) string {
211
+	return fmt.Sprintln(c.convertArgs(a)...)
212
+}
213
+
214
+/*
215
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
216
+interface.  As a result, it integrates cleanly with standard fmt package
217
+printing functions.  The formatter is useful for inline printing of smaller data
218
+types similar to the standard %v format specifier.
219
+
220
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
221
+addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
222
+combinations.  Any other verbs such as %x and %q will be sent to the the
223
+standard fmt package for formatting.  In addition, the custom formatter ignores
224
+the width and precision arguments (however they will still work on the format
225
+specifiers not handled by the custom formatter).
226
+
227
+Typically this function shouldn't be called directly.  It is much easier to make
228
+use of the custom formatter by calling one of the convenience functions such as
229
+c.Printf, c.Println, or c.Printf.
230
+*/
231
+func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
232
+	return newFormatter(c, v)
233
+}
234
+
235
+// Fdump formats and displays the passed arguments to io.Writer w.  It formats
236
+// exactly the same as Dump.
237
+func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
238
+	fdump(c, w, a...)
239
+}
240
+
241
+/*
242
+Dump displays the passed parameters to standard out with newlines, customizable
243
+indentation, and additional debug information such as complete types and all
244
+pointer addresses used to indirect to the final value.  It provides the
245
+following features over the built-in printing facilities provided by the fmt
246
+package:
247
+
248
+	* Pointers are dereferenced and followed
249
+	* Circular data structures are detected and handled properly
250
+	* Custom Stringer/error interfaces are optionally invoked, including
251
+	  on unexported types
252
+	* Custom types which only implement the Stringer/error interfaces via
253
+	  a pointer receiver are optionally invoked when passing non-pointer
254
+	  variables
255
+	* Byte arrays and slices are dumped like the hexdump -C command which
256
+	  includes offsets, byte values in hex, and ASCII output
257
+
258
+The configuration options are controlled by modifying the public members
259
+of c.  See ConfigState for options documentation.
260
+
261
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
262
+get the formatted result as a string.
263
+*/
264
+func (c *ConfigState) Dump(a ...interface{}) {
265
+	fdump(c, os.Stdout, a...)
266
+}
267
+
268
+// Sdump returns a string with the passed arguments formatted exactly the same
269
+// as Dump.
270
+func (c *ConfigState) Sdump(a ...interface{}) string {
271
+	var buf bytes.Buffer
272
+	fdump(c, &buf, a...)
273
+	return buf.String()
274
+}
275
+
276
+// convertArgs accepts a slice of arguments and returns a slice of the same
277
+// length with each argument converted to a spew Formatter interface using
278
+// the ConfigState associated with s.
279
+func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
280
+	formatters = make([]interface{}, len(args))
281
+	for index, arg := range args {
282
+		formatters[index] = newFormatter(c, arg)
283
+	}
284
+	return formatters
285
+}
286
+
287
+// NewDefaultConfig returns a ConfigState with the following default settings.
288
+//
289
+// 	Indent: " "
290
+// 	MaxDepth: 0
291
+// 	DisableMethods: false
292
+// 	DisablePointerMethods: false
293
+// 	ContinueOnMethod: false
294
+// 	SortKeys: false
295
+func NewDefaultConfig() *ConfigState {
296
+	return &ConfigState{Indent: " "}
297
+}

+ 202
- 0
vendor/github.com/davecgh/go-spew/spew/doc.go Bestand weergeven

@@ -0,0 +1,202 @@
1
+/*
2
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+/*
18
+Package spew implements a deep pretty printer for Go data structures to aid in
19
+debugging.
20
+
21
+A quick overview of the additional features spew provides over the built-in
22
+printing facilities for Go data types are as follows:
23
+
24
+	* Pointers are dereferenced and followed
25
+	* Circular data structures are detected and handled properly
26
+	* Custom Stringer/error interfaces are optionally invoked, including
27
+	  on unexported types
28
+	* Custom types which only implement the Stringer/error interfaces via
29
+	  a pointer receiver are optionally invoked when passing non-pointer
30
+	  variables
31
+	* Byte arrays and slices are dumped like the hexdump -C command which
32
+	  includes offsets, byte values in hex, and ASCII output (only when using
33
+	  Dump style)
34
+
35
+There are two different approaches spew allows for dumping Go data structures:
36
+
37
+	* Dump style which prints with newlines, customizable indentation,
38
+	  and additional debug information such as types and all pointer addresses
39
+	  used to indirect to the final value
40
+	* A custom Formatter interface that integrates cleanly with the standard fmt
41
+	  package and replaces %v, %+v, %#v, and %#+v to provide inline printing
42
+	  similar to the default %v while providing the additional functionality
43
+	  outlined above and passing unsupported format verbs such as %x and %q
44
+	  along to fmt
45
+
46
+Quick Start
47
+
48
+This section demonstrates how to quickly get started with spew.  See the
49
+sections below for further details on formatting and configuration options.
50
+
51
+To dump a variable with full newlines, indentation, type, and pointer
52
+information use Dump, Fdump, or Sdump:
53
+	spew.Dump(myVar1, myVar2, ...)
54
+	spew.Fdump(someWriter, myVar1, myVar2, ...)
55
+	str := spew.Sdump(myVar1, myVar2, ...)
56
+
57
+Alternatively, if you would prefer to use format strings with a compacted inline
58
+printing style, use the convenience wrappers Printf, Fprintf, etc with
59
+%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
60
+%#+v (adds types and pointer addresses):
61
+	spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
62
+	spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
63
+	spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
64
+	spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
65
+
66
+Configuration Options
67
+
68
+Configuration of spew is handled by fields in the ConfigState type.  For
69
+convenience, all of the top-level functions use a global state available
70
+via the spew.Config global.
71
+
72
+It is also possible to create a ConfigState instance that provides methods
73
+equivalent to the top-level functions.  This allows concurrent configuration
74
+options.  See the ConfigState documentation for more details.
75
+
76
+The following configuration options are available:
77
+	* Indent
78
+		String to use for each indentation level for Dump functions.
79
+		It is a single space by default.  A popular alternative is "\t".
80
+
81
+	* MaxDepth
82
+		Maximum number of levels to descend into nested data structures.
83
+		There is no limit by default.
84
+
85
+	* DisableMethods
86
+		Disables invocation of error and Stringer interface methods.
87
+		Method invocation is enabled by default.
88
+
89
+	* DisablePointerMethods
90
+		Disables invocation of error and Stringer interface methods on types
91
+		which only accept pointer receivers from non-pointer variables.
92
+		Pointer method invocation is enabled by default.
93
+
94
+	* ContinueOnMethod
95
+		Enables recursion into types after invoking error and Stringer interface
96
+		methods. Recursion after method invocation is disabled by default.
97
+
98
+	* SortKeys
99
+		Specifies map keys should be sorted before being printed. Use
100
+		this to have a more deterministic, diffable output.  Note that
101
+		only native types (bool, int, uint, floats, uintptr and string)
102
+		and types which implement error or Stringer interfaces are
103
+		supported with other types sorted according to the
104
+		reflect.Value.String() output which guarantees display
105
+		stability.  Natural map order is used by default.
106
+
107
+	* SpewKeys
108
+		Specifies that, as a last resort attempt, map keys should be
109
+		spewed to strings and sorted by those strings.  This is only
110
+		considered if SortKeys is true.
111
+
112
+Dump Usage
113
+
114
+Simply call spew.Dump with a list of variables you want to dump:
115
+
116
+	spew.Dump(myVar1, myVar2, ...)
117
+
118
+You may also call spew.Fdump if you would prefer to output to an arbitrary
119
+io.Writer.  For example, to dump to standard error:
120
+
121
+	spew.Fdump(os.Stderr, myVar1, myVar2, ...)
122
+
123
+A third option is to call spew.Sdump to get the formatted output as a string:
124
+
125
+	str := spew.Sdump(myVar1, myVar2, ...)
126
+
127
+Sample Dump Output
128
+
129
+See the Dump example for details on the setup of the types and variables being
130
+shown here.
131
+
132
+	(main.Foo) {
133
+	 unexportedField: (*main.Bar)(0xf84002e210)({
134
+	  flag: (main.Flag) flagTwo,
135
+	  data: (uintptr) <nil>
136
+	 }),
137
+	 ExportedField: (map[interface {}]interface {}) (len=1) {
138
+	  (string) (len=3) "one": (bool) true
139
+	 }
140
+	}
141
+
142
+Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
143
+command as shown.
144
+	([]uint8) (len=32 cap=32) {
145
+	 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20  |............... |
146
+	 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!"#$%&'()*+,-./0|
147
+	 00000020  31 32                                             |12|
148
+	}
149
+
150
+Custom Formatter
151
+
152
+Spew provides a custom formatter that implements the fmt.Formatter interface
153
+so that it integrates cleanly with standard fmt package printing functions. The
154
+formatter is useful for inline printing of smaller data types similar to the
155
+standard %v format specifier.
156
+
157
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
158
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
159
+combinations.  Any other verbs such as %x and %q will be sent to the the
160
+standard fmt package for formatting.  In addition, the custom formatter ignores
161
+the width and precision arguments (however they will still work on the format
162
+specifiers not handled by the custom formatter).
163
+
164
+Custom Formatter Usage
165
+
166
+The simplest way to make use of the spew custom formatter is to call one of the
167
+convenience functions such as spew.Printf, spew.Println, or spew.Printf.  The
168
+functions have syntax you are most likely already familiar with:
169
+
170
+	spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
171
+	spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
172
+	spew.Println(myVar, myVar2)
173
+	spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
174
+	spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
175
+
176
+See the Index for the full list convenience functions.
177
+
178
+Sample Formatter Output
179
+
180
+Double pointer to a uint8:
181
+	  %v: <**>5
182
+	 %+v: <**>(0xf8400420d0->0xf8400420c8)5
183
+	 %#v: (**uint8)5
184
+	%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
185
+
186
+Pointer to circular struct with a uint8 field and a pointer to itself:
187
+	  %v: <*>{1 <*><shown>}
188
+	 %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
189
+	 %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
190
+	%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
191
+
192
+See the Printf example for details on the setup of variables being shown
193
+here.
194
+
195
+Errors
196
+
197
+Since it is possible for custom Stringer/error interfaces to panic, spew
198
+detects them and handles them internally by printing the panic information
199
+inline with the output.  Since spew is intended to provide deep pretty printing
200
+capabilities on structures, it intentionally does not return any errors.
201
+*/
202
+package spew

+ 509
- 0
vendor/github.com/davecgh/go-spew/spew/dump.go Bestand weergeven

@@ -0,0 +1,509 @@
1
+/*
2
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+package spew
18
+
19
+import (
20
+	"bytes"
21
+	"encoding/hex"
22
+	"fmt"
23
+	"io"
24
+	"os"
25
+	"reflect"
26
+	"regexp"
27
+	"strconv"
28
+	"strings"
29
+)
30
+
31
+var (
32
+	// uint8Type is a reflect.Type representing a uint8.  It is used to
33
+	// convert cgo types to uint8 slices for hexdumping.
34
+	uint8Type = reflect.TypeOf(uint8(0))
35
+
36
+	// cCharRE is a regular expression that matches a cgo char.
37
+	// It is used to detect character arrays to hexdump them.
38
+	cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
39
+
40
+	// cUnsignedCharRE is a regular expression that matches a cgo unsigned
41
+	// char.  It is used to detect unsigned character arrays to hexdump
42
+	// them.
43
+	cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
44
+
45
+	// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
46
+	// It is used to detect uint8_t arrays to hexdump them.
47
+	cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
48
+)
49
+
50
+// dumpState contains information about the state of a dump operation.
51
+type dumpState struct {
52
+	w                io.Writer
53
+	depth            int
54
+	pointers         map[uintptr]int
55
+	ignoreNextType   bool
56
+	ignoreNextIndent bool
57
+	cs               *ConfigState
58
+}
59
+
60
+// indent performs indentation according to the depth level and cs.Indent
61
+// option.
62
+func (d *dumpState) indent() {
63
+	if d.ignoreNextIndent {
64
+		d.ignoreNextIndent = false
65
+		return
66
+	}
67
+	d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
68
+}
69
+
70
+// unpackValue returns values inside of non-nil interfaces when possible.
71
+// This is useful for data types like structs, arrays, slices, and maps which
72
+// can contain varying types packed inside an interface.
73
+func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
74
+	if v.Kind() == reflect.Interface && !v.IsNil() {
75
+		v = v.Elem()
76
+	}
77
+	return v
78
+}
79
+
80
+// dumpPtr handles formatting of pointers by indirecting them as necessary.
81
+func (d *dumpState) dumpPtr(v reflect.Value) {
82
+	// Remove pointers at or below the current depth from map used to detect
83
+	// circular refs.
84
+	for k, depth := range d.pointers {
85
+		if depth >= d.depth {
86
+			delete(d.pointers, k)
87
+		}
88
+	}
89
+
90
+	// Keep list of all dereferenced pointers to show later.
91
+	pointerChain := make([]uintptr, 0)
92
+
93
+	// Figure out how many levels of indirection there are by dereferencing
94
+	// pointers and unpacking interfaces down the chain while detecting circular
95
+	// references.
96
+	nilFound := false
97
+	cycleFound := false
98
+	indirects := 0
99
+	ve := v
100
+	for ve.Kind() == reflect.Ptr {
101
+		if ve.IsNil() {
102
+			nilFound = true
103
+			break
104
+		}
105
+		indirects++
106
+		addr := ve.Pointer()
107
+		pointerChain = append(pointerChain, addr)
108
+		if pd, ok := d.pointers[addr]; ok && pd < d.depth {
109
+			cycleFound = true
110
+			indirects--
111
+			break
112
+		}
113
+		d.pointers[addr] = d.depth
114
+
115
+		ve = ve.Elem()
116
+		if ve.Kind() == reflect.Interface {
117
+			if ve.IsNil() {
118
+				nilFound = true
119
+				break
120
+			}
121
+			ve = ve.Elem()
122
+		}
123
+	}
124
+
125
+	// Display type information.
126
+	d.w.Write(openParenBytes)
127
+	d.w.Write(bytes.Repeat(asteriskBytes, indirects))
128
+	d.w.Write([]byte(ve.Type().String()))
129
+	d.w.Write(closeParenBytes)
130
+
131
+	// Display pointer information.
132
+	if len(pointerChain) > 0 {
133
+		d.w.Write(openParenBytes)
134
+		for i, addr := range pointerChain {
135
+			if i > 0 {
136
+				d.w.Write(pointerChainBytes)
137
+			}
138
+			printHexPtr(d.w, addr)
139
+		}
140
+		d.w.Write(closeParenBytes)
141
+	}
142
+
143
+	// Display dereferenced value.
144
+	d.w.Write(openParenBytes)
145
+	switch {
146
+	case nilFound == true:
147
+		d.w.Write(nilAngleBytes)
148
+
149
+	case cycleFound == true:
150
+		d.w.Write(circularBytes)
151
+
152
+	default:
153
+		d.ignoreNextType = true
154
+		d.dump(ve)
155
+	}
156
+	d.w.Write(closeParenBytes)
157
+}
158
+
159
+// dumpSlice handles formatting of arrays and slices.  Byte (uint8 under
160
+// reflection) arrays and slices are dumped in hexdump -C fashion.
161
+func (d *dumpState) dumpSlice(v reflect.Value) {
162
+	// Determine whether this type should be hex dumped or not.  Also,
163
+	// for types which should be hexdumped, try to use the underlying data
164
+	// first, then fall back to trying to convert them to a uint8 slice.
165
+	var buf []uint8
166
+	doConvert := false
167
+	doHexDump := false
168
+	numEntries := v.Len()
169
+	if numEntries > 0 {
170
+		vt := v.Index(0).Type()
171
+		vts := vt.String()
172
+		switch {
173
+		// C types that need to be converted.
174
+		case cCharRE.MatchString(vts):
175
+			fallthrough
176
+		case cUnsignedCharRE.MatchString(vts):
177
+			fallthrough
178
+		case cUint8tCharRE.MatchString(vts):
179
+			doConvert = true
180
+
181
+		// Try to use existing uint8 slices and fall back to converting
182
+		// and copying if that fails.
183
+		case vt.Kind() == reflect.Uint8:
184
+			// We need an addressable interface to convert the type
185
+			// to a byte slice.  However, the reflect package won't
186
+			// give us an interface on certain things like
187
+			// unexported struct fields in order to enforce
188
+			// visibility rules.  We use unsafe, when available, to
189
+			// bypass these restrictions since this package does not
190
+			// mutate the values.
191
+			vs := v
192
+			if !vs.CanInterface() || !vs.CanAddr() {
193
+				vs = unsafeReflectValue(vs)
194
+			}
195
+			if !UnsafeDisabled {
196
+				vs = vs.Slice(0, numEntries)
197
+
198
+				// Use the existing uint8 slice if it can be
199
+				// type asserted.
200
+				iface := vs.Interface()
201
+				if slice, ok := iface.([]uint8); ok {
202
+					buf = slice
203
+					doHexDump = true
204
+					break
205
+				}
206
+			}
207
+
208
+			// The underlying data needs to be converted if it can't
209
+			// be type asserted to a uint8 slice.
210
+			doConvert = true
211
+		}
212
+
213
+		// Copy and convert the underlying type if needed.
214
+		if doConvert && vt.ConvertibleTo(uint8Type) {
215
+			// Convert and copy each element into a uint8 byte
216
+			// slice.
217
+			buf = make([]uint8, numEntries)
218
+			for i := 0; i < numEntries; i++ {
219
+				vv := v.Index(i)
220
+				buf[i] = uint8(vv.Convert(uint8Type).Uint())
221
+			}
222
+			doHexDump = true
223
+		}
224
+	}
225
+
226
+	// Hexdump the entire slice as needed.
227
+	if doHexDump {
228
+		indent := strings.Repeat(d.cs.Indent, d.depth)
229
+		str := indent + hex.Dump(buf)
230
+		str = strings.Replace(str, "\n", "\n"+indent, -1)
231
+		str = strings.TrimRight(str, d.cs.Indent)
232
+		d.w.Write([]byte(str))
233
+		return
234
+	}
235
+
236
+	// Recursively call dump for each item.
237
+	for i := 0; i < numEntries; i++ {
238
+		d.dump(d.unpackValue(v.Index(i)))
239
+		if i < (numEntries - 1) {
240
+			d.w.Write(commaNewlineBytes)
241
+		} else {
242
+			d.w.Write(newlineBytes)
243
+		}
244
+	}
245
+}
246
+
247
+// dump is the main workhorse for dumping a value.  It uses the passed reflect
248
+// value to figure out what kind of object we are dealing with and formats it
249
+// appropriately.  It is a recursive function, however circular data structures
250
+// are detected and handled properly.
251
+func (d *dumpState) dump(v reflect.Value) {
252
+	// Handle invalid reflect values immediately.
253
+	kind := v.Kind()
254
+	if kind == reflect.Invalid {
255
+		d.w.Write(invalidAngleBytes)
256
+		return
257
+	}
258
+
259
+	// Handle pointers specially.
260
+	if kind == reflect.Ptr {
261
+		d.indent()
262
+		d.dumpPtr(v)
263
+		return
264
+	}
265
+
266
+	// Print type information unless already handled elsewhere.
267
+	if !d.ignoreNextType {
268
+		d.indent()
269
+		d.w.Write(openParenBytes)
270
+		d.w.Write([]byte(v.Type().String()))
271
+		d.w.Write(closeParenBytes)
272
+		d.w.Write(spaceBytes)
273
+	}
274
+	d.ignoreNextType = false
275
+
276
+	// Display length and capacity if the built-in len and cap functions
277
+	// work with the value's kind and the len/cap itself is non-zero.
278
+	valueLen, valueCap := 0, 0
279
+	switch v.Kind() {
280
+	case reflect.Array, reflect.Slice, reflect.Chan:
281
+		valueLen, valueCap = v.Len(), v.Cap()
282
+	case reflect.Map, reflect.String:
283
+		valueLen = v.Len()
284
+	}
285
+	if valueLen != 0 || valueCap != 0 {
286
+		d.w.Write(openParenBytes)
287
+		if valueLen != 0 {
288
+			d.w.Write(lenEqualsBytes)
289
+			printInt(d.w, int64(valueLen), 10)
290
+		}
291
+		if valueCap != 0 {
292
+			if valueLen != 0 {
293
+				d.w.Write(spaceBytes)
294
+			}
295
+			d.w.Write(capEqualsBytes)
296
+			printInt(d.w, int64(valueCap), 10)
297
+		}
298
+		d.w.Write(closeParenBytes)
299
+		d.w.Write(spaceBytes)
300
+	}
301
+
302
+	// Call Stringer/error interfaces if they exist and the handle methods flag
303
+	// is enabled
304
+	if !d.cs.DisableMethods {
305
+		if (kind != reflect.Invalid) && (kind != reflect.Interface) {
306
+			if handled := handleMethods(d.cs, d.w, v); handled {
307
+				return
308
+			}
309
+		}
310
+	}
311
+
312
+	switch kind {
313
+	case reflect.Invalid:
314
+		// Do nothing.  We should never get here since invalid has already
315
+		// been handled above.
316
+
317
+	case reflect.Bool:
318
+		printBool(d.w, v.Bool())
319
+
320
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
321
+		printInt(d.w, v.Int(), 10)
322
+
323
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
324
+		printUint(d.w, v.Uint(), 10)
325
+
326
+	case reflect.Float32:
327
+		printFloat(d.w, v.Float(), 32)
328
+
329
+	case reflect.Float64:
330
+		printFloat(d.w, v.Float(), 64)
331
+
332
+	case reflect.Complex64:
333
+		printComplex(d.w, v.Complex(), 32)
334
+
335
+	case reflect.Complex128:
336
+		printComplex(d.w, v.Complex(), 64)
337
+
338
+	case reflect.Slice:
339
+		if v.IsNil() {
340
+			d.w.Write(nilAngleBytes)
341
+			break
342
+		}
343
+		fallthrough
344
+
345
+	case reflect.Array:
346
+		d.w.Write(openBraceNewlineBytes)
347
+		d.depth++
348
+		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
349
+			d.indent()
350
+			d.w.Write(maxNewlineBytes)
351
+		} else {
352
+			d.dumpSlice(v)
353
+		}
354
+		d.depth--
355
+		d.indent()
356
+		d.w.Write(closeBraceBytes)
357
+
358
+	case reflect.String:
359
+		d.w.Write([]byte(strconv.Quote(v.String())))
360
+
361
+	case reflect.Interface:
362
+		// The only time we should get here is for nil interfaces due to
363
+		// unpackValue calls.
364
+		if v.IsNil() {
365
+			d.w.Write(nilAngleBytes)
366
+		}
367
+
368
+	case reflect.Ptr:
369
+		// Do nothing.  We should never get here since pointers have already
370
+		// been handled above.
371
+
372
+	case reflect.Map:
373
+		// nil maps should be indicated as different than empty maps
374
+		if v.IsNil() {
375
+			d.w.Write(nilAngleBytes)
376
+			break
377
+		}
378
+
379
+		d.w.Write(openBraceNewlineBytes)
380
+		d.depth++
381
+		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
382
+			d.indent()
383
+			d.w.Write(maxNewlineBytes)
384
+		} else {
385
+			numEntries := v.Len()
386
+			keys := v.MapKeys()
387
+			if d.cs.SortKeys {
388
+				sortValues(keys, d.cs)
389
+			}
390
+			for i, key := range keys {
391
+				d.dump(d.unpackValue(key))
392
+				d.w.Write(colonSpaceBytes)
393
+				d.ignoreNextIndent = true
394
+				d.dump(d.unpackValue(v.MapIndex(key)))
395
+				if i < (numEntries - 1) {
396
+					d.w.Write(commaNewlineBytes)
397
+				} else {
398
+					d.w.Write(newlineBytes)
399
+				}
400
+			}
401
+		}
402
+		d.depth--
403
+		d.indent()
404
+		d.w.Write(closeBraceBytes)
405
+
406
+	case reflect.Struct:
407
+		d.w.Write(openBraceNewlineBytes)
408
+		d.depth++
409
+		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
410
+			d.indent()
411
+			d.w.Write(maxNewlineBytes)
412
+		} else {
413
+			vt := v.Type()
414
+			numFields := v.NumField()
415
+			for i := 0; i < numFields; i++ {
416
+				d.indent()
417
+				vtf := vt.Field(i)
418
+				d.w.Write([]byte(vtf.Name))
419
+				d.w.Write(colonSpaceBytes)
420
+				d.ignoreNextIndent = true
421
+				d.dump(d.unpackValue(v.Field(i)))
422
+				if i < (numFields - 1) {
423
+					d.w.Write(commaNewlineBytes)
424
+				} else {
425
+					d.w.Write(newlineBytes)
426
+				}
427
+			}
428
+		}
429
+		d.depth--
430
+		d.indent()
431
+		d.w.Write(closeBraceBytes)
432
+
433
+	case reflect.Uintptr:
434
+		printHexPtr(d.w, uintptr(v.Uint()))
435
+
436
+	case reflect.UnsafePointer, reflect.Chan, reflect.Func:
437
+		printHexPtr(d.w, v.Pointer())
438
+
439
+	// There were not any other types at the time this code was written, but
440
+	// fall back to letting the default fmt package handle it in case any new
441
+	// types are added.
442
+	default:
443
+		if v.CanInterface() {
444
+			fmt.Fprintf(d.w, "%v", v.Interface())
445
+		} else {
446
+			fmt.Fprintf(d.w, "%v", v.String())
447
+		}
448
+	}
449
+}
450
+
451
+// fdump is a helper function to consolidate the logic from the various public
452
+// methods which take varying writers and config states.
453
+func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
454
+	for _, arg := range a {
455
+		if arg == nil {
456
+			w.Write(interfaceBytes)
457
+			w.Write(spaceBytes)
458
+			w.Write(nilAngleBytes)
459
+			w.Write(newlineBytes)
460
+			continue
461
+		}
462
+
463
+		d := dumpState{w: w, cs: cs}
464
+		d.pointers = make(map[uintptr]int)
465
+		d.dump(reflect.ValueOf(arg))
466
+		d.w.Write(newlineBytes)
467
+	}
468
+}
469
+
470
+// Fdump formats and displays the passed arguments to io.Writer w.  It formats
471
+// exactly the same as Dump.
472
+func Fdump(w io.Writer, a ...interface{}) {
473
+	fdump(&Config, w, a...)
474
+}
475
+
476
+// Sdump returns a string with the passed arguments formatted exactly the same
477
+// as Dump.
478
+func Sdump(a ...interface{}) string {
479
+	var buf bytes.Buffer
480
+	fdump(&Config, &buf, a...)
481
+	return buf.String()
482
+}
483
+
484
+/*
485
+Dump displays the passed parameters to standard out with newlines, customizable
486
+indentation, and additional debug information such as complete types and all
487
+pointer addresses used to indirect to the final value.  It provides the
488
+following features over the built-in printing facilities provided by the fmt
489
+package:
490
+
491
+	* Pointers are dereferenced and followed
492
+	* Circular data structures are detected and handled properly
493
+	* Custom Stringer/error interfaces are optionally invoked, including
494
+	  on unexported types
495
+	* Custom types which only implement the Stringer/error interfaces via
496
+	  a pointer receiver are optionally invoked when passing non-pointer
497
+	  variables
498
+	* Byte arrays and slices are dumped like the hexdump -C command which
499
+	  includes offsets, byte values in hex, and ASCII output
500
+
501
+The configuration options are controlled by an exported package global,
502
+spew.Config.  See ConfigState for options documentation.
503
+
504
+See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
505
+get the formatted result as a string.
506
+*/
507
+func Dump(a ...interface{}) {
508
+	fdump(&Config, os.Stdout, a...)
509
+}

+ 419
- 0
vendor/github.com/davecgh/go-spew/spew/format.go Bestand weergeven

@@ -0,0 +1,419 @@
1
+/*
2
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+package spew
18
+
19
+import (
20
+	"bytes"
21
+	"fmt"
22
+	"reflect"
23
+	"strconv"
24
+	"strings"
25
+)
26
+
27
+// supportedFlags is a list of all the character flags supported by fmt package.
28
+const supportedFlags = "0-+# "
29
+
30
+// formatState implements the fmt.Formatter interface and contains information
31
+// about the state of a formatting operation.  The NewFormatter function can
32
+// be used to get a new Formatter which can be used directly as arguments
33
+// in standard fmt package printing calls.
34
+type formatState struct {
35
+	value          interface{}
36
+	fs             fmt.State
37
+	depth          int
38
+	pointers       map[uintptr]int
39
+	ignoreNextType bool
40
+	cs             *ConfigState
41
+}
42
+
43
+// buildDefaultFormat recreates the original format string without precision
44
+// and width information to pass in to fmt.Sprintf in the case of an
45
+// unrecognized type.  Unless new types are added to the language, this
46
+// function won't ever be called.
47
+func (f *formatState) buildDefaultFormat() (format string) {
48
+	buf := bytes.NewBuffer(percentBytes)
49
+
50
+	for _, flag := range supportedFlags {
51
+		if f.fs.Flag(int(flag)) {
52
+			buf.WriteRune(flag)
53
+		}
54
+	}
55
+
56
+	buf.WriteRune('v')
57
+
58
+	format = buf.String()
59
+	return format
60
+}
61
+
62
+// constructOrigFormat recreates the original format string including precision
63
+// and width information to pass along to the standard fmt package.  This allows
64
+// automatic deferral of all format strings this package doesn't support.
65
+func (f *formatState) constructOrigFormat(verb rune) (format string) {
66
+	buf := bytes.NewBuffer(percentBytes)
67
+
68
+	for _, flag := range supportedFlags {
69
+		if f.fs.Flag(int(flag)) {
70
+			buf.WriteRune(flag)
71
+		}
72
+	}
73
+
74
+	if width, ok := f.fs.Width(); ok {
75
+		buf.WriteString(strconv.Itoa(width))
76
+	}
77
+
78
+	if precision, ok := f.fs.Precision(); ok {
79
+		buf.Write(precisionBytes)
80
+		buf.WriteString(strconv.Itoa(precision))
81
+	}
82
+
83
+	buf.WriteRune(verb)
84
+
85
+	format = buf.String()
86
+	return format
87
+}
88
+
89
+// unpackValue returns values inside of non-nil interfaces when possible and
90
+// ensures that types for values which have been unpacked from an interface
91
+// are displayed when the show types flag is also set.
92
+// This is useful for data types like structs, arrays, slices, and maps which
93
+// can contain varying types packed inside an interface.
94
+func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
95
+	if v.Kind() == reflect.Interface {
96
+		f.ignoreNextType = false
97
+		if !v.IsNil() {
98
+			v = v.Elem()
99
+		}
100
+	}
101
+	return v
102
+}
103
+
104
+// formatPtr handles formatting of pointers by indirecting them as necessary.
105
+func (f *formatState) formatPtr(v reflect.Value) {
106
+	// Display nil if top level pointer is nil.
107
+	showTypes := f.fs.Flag('#')
108
+	if v.IsNil() && (!showTypes || f.ignoreNextType) {
109
+		f.fs.Write(nilAngleBytes)
110
+		return
111
+	}
112
+
113
+	// Remove pointers at or below the current depth from map used to detect
114
+	// circular refs.
115
+	for k, depth := range f.pointers {
116
+		if depth >= f.depth {
117
+			delete(f.pointers, k)
118
+		}
119
+	}
120
+
121
+	// Keep list of all dereferenced pointers to possibly show later.
122
+	pointerChain := make([]uintptr, 0)
123
+
124
+	// Figure out how many levels of indirection there are by derferencing
125
+	// pointers and unpacking interfaces down the chain while detecting circular
126
+	// references.
127
+	nilFound := false
128
+	cycleFound := false
129
+	indirects := 0
130
+	ve := v
131
+	for ve.Kind() == reflect.Ptr {
132
+		if ve.IsNil() {
133
+			nilFound = true
134
+			break
135
+		}
136
+		indirects++
137
+		addr := ve.Pointer()
138
+		pointerChain = append(pointerChain, addr)
139
+		if pd, ok := f.pointers[addr]; ok && pd < f.depth {
140
+			cycleFound = true
141
+			indirects--
142
+			break
143
+		}
144
+		f.pointers[addr] = f.depth
145
+
146
+		ve = ve.Elem()
147
+		if ve.Kind() == reflect.Interface {
148
+			if ve.IsNil() {
149
+				nilFound = true
150
+				break
151
+			}
152
+			ve = ve.Elem()
153
+		}
154
+	}
155
+
156
+	// Display type or indirection level depending on flags.
157
+	if showTypes && !f.ignoreNextType {
158
+		f.fs.Write(openParenBytes)
159
+		f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
160
+		f.fs.Write([]byte(ve.Type().String()))
161
+		f.fs.Write(closeParenBytes)
162
+	} else {
163
+		if nilFound || cycleFound {
164
+			indirects += strings.Count(ve.Type().String(), "*")
165
+		}
166
+		f.fs.Write(openAngleBytes)
167
+		f.fs.Write([]byte(strings.Repeat("*", indirects)))
168
+		f.fs.Write(closeAngleBytes)
169
+	}
170
+
171
+	// Display pointer information depending on flags.
172
+	if f.fs.Flag('+') && (len(pointerChain) > 0) {
173
+		f.fs.Write(openParenBytes)
174
+		for i, addr := range pointerChain {
175
+			if i > 0 {
176
+				f.fs.Write(pointerChainBytes)
177
+			}
178
+			printHexPtr(f.fs, addr)
179
+		}
180
+		f.fs.Write(closeParenBytes)
181
+	}
182
+
183
+	// Display dereferenced value.
184
+	switch {
185
+	case nilFound == true:
186
+		f.fs.Write(nilAngleBytes)
187
+
188
+	case cycleFound == true:
189
+		f.fs.Write(circularShortBytes)
190
+
191
+	default:
192
+		f.ignoreNextType = true
193
+		f.format(ve)
194
+	}
195
+}
196
+
197
+// format is the main workhorse for providing the Formatter interface.  It
198
+// uses the passed reflect value to figure out what kind of object we are
199
+// dealing with and formats it appropriately.  It is a recursive function,
200
+// however circular data structures are detected and handled properly.
201
+func (f *formatState) format(v reflect.Value) {
202
+	// Handle invalid reflect values immediately.
203
+	kind := v.Kind()
204
+	if kind == reflect.Invalid {
205
+		f.fs.Write(invalidAngleBytes)
206
+		return
207
+	}
208
+
209
+	// Handle pointers specially.
210
+	if kind == reflect.Ptr {
211
+		f.formatPtr(v)
212
+		return
213
+	}
214
+
215
+	// Print type information unless already handled elsewhere.
216
+	if !f.ignoreNextType && f.fs.Flag('#') {
217
+		f.fs.Write(openParenBytes)
218
+		f.fs.Write([]byte(v.Type().String()))
219
+		f.fs.Write(closeParenBytes)
220
+	}
221
+	f.ignoreNextType = false
222
+
223
+	// Call Stringer/error interfaces if they exist and the handle methods
224
+	// flag is enabled.
225
+	if !f.cs.DisableMethods {
226
+		if (kind != reflect.Invalid) && (kind != reflect.Interface) {
227
+			if handled := handleMethods(f.cs, f.fs, v); handled {
228
+				return
229
+			}
230
+		}
231
+	}
232
+
233
+	switch kind {
234
+	case reflect.Invalid:
235
+		// Do nothing.  We should never get here since invalid has already
236
+		// been handled above.
237
+
238
+	case reflect.Bool:
239
+		printBool(f.fs, v.Bool())
240
+
241
+	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
242
+		printInt(f.fs, v.Int(), 10)
243
+
244
+	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
245
+		printUint(f.fs, v.Uint(), 10)
246
+
247
+	case reflect.Float32:
248
+		printFloat(f.fs, v.Float(), 32)
249
+
250
+	case reflect.Float64:
251
+		printFloat(f.fs, v.Float(), 64)
252
+
253
+	case reflect.Complex64:
254
+		printComplex(f.fs, v.Complex(), 32)
255
+
256
+	case reflect.Complex128:
257
+		printComplex(f.fs, v.Complex(), 64)
258
+
259
+	case reflect.Slice:
260
+		if v.IsNil() {
261
+			f.fs.Write(nilAngleBytes)
262
+			break
263
+		}
264
+		fallthrough
265
+
266
+	case reflect.Array:
267
+		f.fs.Write(openBracketBytes)
268
+		f.depth++
269
+		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
270
+			f.fs.Write(maxShortBytes)
271
+		} else {
272
+			numEntries := v.Len()
273
+			for i := 0; i < numEntries; i++ {
274
+				if i > 0 {
275
+					f.fs.Write(spaceBytes)
276
+				}
277
+				f.ignoreNextType = true
278
+				f.format(f.unpackValue(v.Index(i)))
279
+			}
280
+		}
281
+		f.depth--
282
+		f.fs.Write(closeBracketBytes)
283
+
284
+	case reflect.String:
285
+		f.fs.Write([]byte(v.String()))
286
+
287
+	case reflect.Interface:
288
+		// The only time we should get here is for nil interfaces due to
289
+		// unpackValue calls.
290
+		if v.IsNil() {
291
+			f.fs.Write(nilAngleBytes)
292
+		}
293
+
294
+	case reflect.Ptr:
295
+		// Do nothing.  We should never get here since pointers have already
296
+		// been handled above.
297
+
298
+	case reflect.Map:
299
+		// nil maps should be indicated as different than empty maps
300
+		if v.IsNil() {
301
+			f.fs.Write(nilAngleBytes)
302
+			break
303
+		}
304
+
305
+		f.fs.Write(openMapBytes)
306
+		f.depth++
307
+		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
308
+			f.fs.Write(maxShortBytes)
309
+		} else {
310
+			keys := v.MapKeys()
311
+			if f.cs.SortKeys {
312
+				sortValues(keys, f.cs)
313
+			}
314
+			for i, key := range keys {
315
+				if i > 0 {
316
+					f.fs.Write(spaceBytes)
317
+				}
318
+				f.ignoreNextType = true
319
+				f.format(f.unpackValue(key))
320
+				f.fs.Write(colonBytes)
321
+				f.ignoreNextType = true
322
+				f.format(f.unpackValue(v.MapIndex(key)))
323
+			}
324
+		}
325
+		f.depth--
326
+		f.fs.Write(closeMapBytes)
327
+
328
+	case reflect.Struct:
329
+		numFields := v.NumField()
330
+		f.fs.Write(openBraceBytes)
331
+		f.depth++
332
+		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
333
+			f.fs.Write(maxShortBytes)
334
+		} else {
335
+			vt := v.Type()
336
+			for i := 0; i < numFields; i++ {
337
+				if i > 0 {
338
+					f.fs.Write(spaceBytes)
339
+				}
340
+				vtf := vt.Field(i)
341
+				if f.fs.Flag('+') || f.fs.Flag('#') {
342
+					f.fs.Write([]byte(vtf.Name))
343
+					f.fs.Write(colonBytes)
344
+				}
345
+				f.format(f.unpackValue(v.Field(i)))
346
+			}
347
+		}
348
+		f.depth--
349
+		f.fs.Write(closeBraceBytes)
350
+
351
+	case reflect.Uintptr:
352
+		printHexPtr(f.fs, uintptr(v.Uint()))
353
+
354
+	case reflect.UnsafePointer, reflect.Chan, reflect.Func:
355
+		printHexPtr(f.fs, v.Pointer())
356
+
357
+	// There were not any other types at the time this code was written, but
358
+	// fall back to letting the default fmt package handle it if any get added.
359
+	default:
360
+		format := f.buildDefaultFormat()
361
+		if v.CanInterface() {
362
+			fmt.Fprintf(f.fs, format, v.Interface())
363
+		} else {
364
+			fmt.Fprintf(f.fs, format, v.String())
365
+		}
366
+	}
367
+}
368
+
369
+// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
370
+// details.
371
+func (f *formatState) Format(fs fmt.State, verb rune) {
372
+	f.fs = fs
373
+
374
+	// Use standard formatting for verbs that are not v.
375
+	if verb != 'v' {
376
+		format := f.constructOrigFormat(verb)
377
+		fmt.Fprintf(fs, format, f.value)
378
+		return
379
+	}
380
+
381
+	if f.value == nil {
382
+		if fs.Flag('#') {
383
+			fs.Write(interfaceBytes)
384
+		}
385
+		fs.Write(nilAngleBytes)
386
+		return
387
+	}
388
+
389
+	f.format(reflect.ValueOf(f.value))
390
+}
391
+
392
+// newFormatter is a helper function to consolidate the logic from the various
393
+// public methods which take varying config states.
394
+func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
395
+	fs := &formatState{value: v, cs: cs}
396
+	fs.pointers = make(map[uintptr]int)
397
+	return fs
398
+}
399
+
400
+/*
401
+NewFormatter returns a custom formatter that satisfies the fmt.Formatter
402
+interface.  As a result, it integrates cleanly with standard fmt package
403
+printing functions.  The formatter is useful for inline printing of smaller data
404
+types similar to the standard %v format specifier.
405
+
406
+The custom formatter only responds to the %v (most compact), %+v (adds pointer
407
+addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
408
+combinations.  Any other verbs such as %x and %q will be sent to the the
409
+standard fmt package for formatting.  In addition, the custom formatter ignores
410
+the width and precision arguments (however they will still work on the format
411
+specifiers not handled by the custom formatter).
412
+
413
+Typically this function shouldn't be called directly.  It is much easier to make
414
+use of the custom formatter by calling one of the convenience functions such as
415
+Printf, Println, or Fprintf.
416
+*/
417
+func NewFormatter(v interface{}) fmt.Formatter {
418
+	return newFormatter(&Config, v)
419
+}

+ 148
- 0
vendor/github.com/davecgh/go-spew/spew/spew.go Bestand weergeven

@@ -0,0 +1,148 @@
1
+/*
2
+ * Copyright (c) 2013 Dave Collins <dave@davec.name>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+package spew
18
+
19
+import (
20
+	"fmt"
21
+	"io"
22
+)
23
+
24
+// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
25
+// passed with a default Formatter interface returned by NewFormatter.  It
26
+// returns the formatted string as a value that satisfies error.  See
27
+// NewFormatter for formatting details.
28
+//
29
+// This function is shorthand for the following syntax:
30
+//
31
+//	fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
32
+func Errorf(format string, a ...interface{}) (err error) {
33
+	return fmt.Errorf(format, convertArgs(a)...)
34
+}
35
+
36
+// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
37
+// passed with a default Formatter interface returned by NewFormatter.  It
38
+// returns the number of bytes written and any write error encountered.  See
39
+// NewFormatter for formatting details.
40
+//
41
+// This function is shorthand for the following syntax:
42
+//
43
+//	fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
44
+func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
45
+	return fmt.Fprint(w, convertArgs(a)...)
46
+}
47
+
48
+// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
49
+// passed with a default Formatter interface returned by NewFormatter.  It
50
+// returns the number of bytes written and any write error encountered.  See
51
+// NewFormatter for formatting details.
52
+//
53
+// This function is shorthand for the following syntax:
54
+//
55
+//	fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
56
+func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
57
+	return fmt.Fprintf(w, format, convertArgs(a)...)
58
+}
59
+
60
+// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
61
+// passed with a default Formatter interface returned by NewFormatter.  See
62
+// NewFormatter for formatting details.
63
+//
64
+// This function is shorthand for the following syntax:
65
+//
66
+//	fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
67
+func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
68
+	return fmt.Fprintln(w, convertArgs(a)...)
69
+}
70
+
71
+// Print is a wrapper for fmt.Print that treats each argument as if it were
72
+// passed with a default Formatter interface returned by NewFormatter.  It
73
+// returns the number of bytes written and any write error encountered.  See
74
+// NewFormatter for formatting details.
75
+//
76
+// This function is shorthand for the following syntax:
77
+//
78
+//	fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
79
+func Print(a ...interface{}) (n int, err error) {
80
+	return fmt.Print(convertArgs(a)...)
81
+}
82
+
83
+// Printf is a wrapper for fmt.Printf that treats each argument as if it were
84
+// passed with a default Formatter interface returned by NewFormatter.  It
85
+// returns the number of bytes written and any write error encountered.  See
86
+// NewFormatter for formatting details.
87
+//
88
+// This function is shorthand for the following syntax:
89
+//
90
+//	fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
91
+func Printf(format string, a ...interface{}) (n int, err error) {
92
+	return fmt.Printf(format, convertArgs(a)...)
93
+}
94
+
95
+// Println is a wrapper for fmt.Println that treats each argument as if it were
96
+// passed with a default Formatter interface returned by NewFormatter.  It
97
+// returns the number of bytes written and any write error encountered.  See
98
+// NewFormatter for formatting details.
99
+//
100
+// This function is shorthand for the following syntax:
101
+//
102
+//	fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
103
+func Println(a ...interface{}) (n int, err error) {
104
+	return fmt.Println(convertArgs(a)...)
105
+}
106
+
107
+// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
108
+// passed with a default Formatter interface returned by NewFormatter.  It
109
+// returns the resulting string.  See NewFormatter for formatting details.
110
+//
111
+// This function is shorthand for the following syntax:
112
+//
113
+//	fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
114
+func Sprint(a ...interface{}) string {
115
+	return fmt.Sprint(convertArgs(a)...)
116
+}
117
+
118
+// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
119
+// passed with a default Formatter interface returned by NewFormatter.  It
120
+// returns the resulting string.  See NewFormatter for formatting details.
121
+//
122
+// This function is shorthand for the following syntax:
123
+//
124
+//	fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
125
+func Sprintf(format string, a ...interface{}) string {
126
+	return fmt.Sprintf(format, convertArgs(a)...)
127
+}
128
+
129
+// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
130
+// were passed with a default Formatter interface returned by NewFormatter.  It
131
+// returns the resulting string.  See NewFormatter for formatting details.
132
+//
133
+// This function is shorthand for the following syntax:
134
+//
135
+//	fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
136
+func Sprintln(a ...interface{}) string {
137
+	return fmt.Sprintln(convertArgs(a)...)
138
+}
139
+
140
+// convertArgs accepts a slice of arguments and returns a slice of the same
141
+// length with each argument converted to a default spew Formatter interface.
142
+func convertArgs(args []interface{}) (formatters []interface{}) {
143
+	formatters = make([]interface{}, len(args))
144
+	for index, arg := range args {
145
+		formatters[index] = NewFormatter(arg)
146
+	}
147
+	return formatters
148
+}

+ 54
- 0
vendor/github.com/garyburd/redigo/internal/commandinfo.go Bestand weergeven

@@ -0,0 +1,54 @@
1
+// Copyright 2014 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package internal // import "github.com/garyburd/redigo/internal"
16
+
17
+import (
18
+	"strings"
19
+)
20
+
21
+const (
22
+	WatchState = 1 << iota
23
+	MultiState
24
+	SubscribeState
25
+	MonitorState
26
+)
27
+
28
+type CommandInfo struct {
29
+	Set, Clear int
30
+}
31
+
32
+var commandInfos = map[string]CommandInfo{
33
+	"WATCH":      {Set: WatchState},
34
+	"UNWATCH":    {Clear: WatchState},
35
+	"MULTI":      {Set: MultiState},
36
+	"EXEC":       {Clear: WatchState | MultiState},
37
+	"DISCARD":    {Clear: WatchState | MultiState},
38
+	"PSUBSCRIBE": {Set: SubscribeState},
39
+	"SUBSCRIBE":  {Set: SubscribeState},
40
+	"MONITOR":    {Set: MonitorState},
41
+}
42
+
43
+func init() {
44
+	for n, ci := range commandInfos {
45
+		commandInfos[strings.ToLower(n)] = ci
46
+	}
47
+}
48
+
49
+func LookupCommandInfo(commandName string) CommandInfo {
50
+	if ci, ok := commandInfos[commandName]; ok {
51
+		return ci
52
+	}
53
+	return commandInfos[strings.ToUpper(commandName)]
54
+}

+ 567
- 0
vendor/github.com/garyburd/redigo/redis/conn.go Bestand weergeven

@@ -0,0 +1,567 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import (
18
+	"bufio"
19
+	"bytes"
20
+	"errors"
21
+	"fmt"
22
+	"io"
23
+	"net"
24
+	"net/url"
25
+	"regexp"
26
+	"strconv"
27
+	"sync"
28
+	"time"
29
+)
30
+
31
+// conn is the low-level implementation of Conn
32
+type conn struct {
33
+
34
+	// Shared
35
+	mu      sync.Mutex
36
+	pending int
37
+	err     error
38
+	conn    net.Conn
39
+
40
+	// Read
41
+	readTimeout time.Duration
42
+	br          *bufio.Reader
43
+
44
+	// Write
45
+	writeTimeout time.Duration
46
+	bw           *bufio.Writer
47
+
48
+	// Scratch space for formatting argument length.
49
+	// '*' or '$', length, "\r\n"
50
+	lenScratch [32]byte
51
+
52
+	// Scratch space for formatting integers and floats.
53
+	numScratch [40]byte
54
+}
55
+
56
+// DialTimeout acts like Dial but takes timeouts for establishing the
57
+// connection to the server, writing a command and reading a reply.
58
+//
59
+// Deprecated: Use Dial with options instead.
60
+func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) {
61
+	return Dial(network, address,
62
+		DialConnectTimeout(connectTimeout),
63
+		DialReadTimeout(readTimeout),
64
+		DialWriteTimeout(writeTimeout))
65
+}
66
+
67
+// DialOption specifies an option for dialing a Redis server.
68
+type DialOption struct {
69
+	f func(*dialOptions)
70
+}
71
+
72
+type dialOptions struct {
73
+	readTimeout  time.Duration
74
+	writeTimeout time.Duration
75
+	dial         func(network, addr string) (net.Conn, error)
76
+	db           int
77
+	password     string
78
+}
79
+
80
+// DialReadTimeout specifies the timeout for reading a single command reply.
81
+func DialReadTimeout(d time.Duration) DialOption {
82
+	return DialOption{func(do *dialOptions) {
83
+		do.readTimeout = d
84
+	}}
85
+}
86
+
87
+// DialWriteTimeout specifies the timeout for writing a single command.
88
+func DialWriteTimeout(d time.Duration) DialOption {
89
+	return DialOption{func(do *dialOptions) {
90
+		do.writeTimeout = d
91
+	}}
92
+}
93
+
94
+// DialConnectTimeout specifies the timeout for connecting to the Redis server.
95
+func DialConnectTimeout(d time.Duration) DialOption {
96
+	return DialOption{func(do *dialOptions) {
97
+		dialer := net.Dialer{Timeout: d}
98
+		do.dial = dialer.Dial
99
+	}}
100
+}
101
+
102
+// DialNetDial specifies a custom dial function for creating TCP
103
+// connections. If this option is left out, then net.Dial is
104
+// used. DialNetDial overrides DialConnectTimeout.
105
+func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption {
106
+	return DialOption{func(do *dialOptions) {
107
+		do.dial = dial
108
+	}}
109
+}
110
+
111
+// DialDatabase specifies the database to select when dialing a connection.
112
+func DialDatabase(db int) DialOption {
113
+	return DialOption{func(do *dialOptions) {
114
+		do.db = db
115
+	}}
116
+}
117
+
118
+// DialPassword specifies the password to use when connecting to
119
+// the Redis server.
120
+func DialPassword(password string) DialOption {
121
+	return DialOption{func(do *dialOptions) {
122
+		do.password = password
123
+	}}
124
+}
125
+
126
+// Dial connects to the Redis server at the given network and
127
+// address using the specified options.
128
+func Dial(network, address string, options ...DialOption) (Conn, error) {
129
+	do := dialOptions{
130
+		dial: net.Dial,
131
+	}
132
+	for _, option := range options {
133
+		option.f(&do)
134
+	}
135
+
136
+	netConn, err := do.dial(network, address)
137
+	if err != nil {
138
+		return nil, err
139
+	}
140
+	c := &conn{
141
+		conn:         netConn,
142
+		bw:           bufio.NewWriter(netConn),
143
+		br:           bufio.NewReader(netConn),
144
+		readTimeout:  do.readTimeout,
145
+		writeTimeout: do.writeTimeout,
146
+	}
147
+
148
+	if do.password != "" {
149
+		if _, err := c.Do("AUTH", do.password); err != nil {
150
+			netConn.Close()
151
+			return nil, err
152
+		}
153
+	}
154
+
155
+	if do.db != 0 {
156
+		if _, err := c.Do("SELECT", do.db); err != nil {
157
+			netConn.Close()
158
+			return nil, err
159
+		}
160
+	}
161
+
162
+	return c, nil
163
+}
164
+
165
+var pathDBRegexp = regexp.MustCompile(`/(\d+)\z`)
166
+
167
+// DialURL connects to a Redis server at the given URL using the Redis
168
+// URI scheme. URLs should follow the draft IANA specification for the
169
+// scheme (https://www.iana.org/assignments/uri-schemes/prov/redis).
170
+func DialURL(rawurl string, options ...DialOption) (Conn, error) {
171
+	u, err := url.Parse(rawurl)
172
+	if err != nil {
173
+		return nil, err
174
+	}
175
+
176
+	if u.Scheme != "redis" {
177
+		return nil, fmt.Errorf("invalid redis URL scheme: %s", u.Scheme)
178
+	}
179
+
180
+	// As per the IANA draft spec, the host defaults to localhost and
181
+	// the port defaults to 6379.
182
+	host, port, err := net.SplitHostPort(u.Host)
183
+	if err != nil {
184
+		// assume port is missing
185
+		host = u.Host
186
+		port = "6379"
187
+	}
188
+	if host == "" {
189
+		host = "localhost"
190
+	}
191
+	address := net.JoinHostPort(host, port)
192
+
193
+	if u.User != nil {
194
+		password, isSet := u.User.Password()
195
+		if isSet {
196
+			options = append(options, DialPassword(password))
197
+		}
198
+	}
199
+
200
+	match := pathDBRegexp.FindStringSubmatch(u.Path)
201
+	if len(match) == 2 {
202
+		db, err := strconv.Atoi(match[1])
203
+		if err != nil {
204
+			return nil, fmt.Errorf("invalid database: %s", u.Path[1:])
205
+		}
206
+		if db != 0 {
207
+			options = append(options, DialDatabase(db))
208
+		}
209
+	} else if u.Path != "" {
210
+		return nil, fmt.Errorf("invalid database: %s", u.Path[1:])
211
+	}
212
+
213
+	return Dial("tcp", address, options...)
214
+}
215
+
216
+// NewConn returns a new Redigo connection for the given net connection.
217
+func NewConn(netConn net.Conn, readTimeout, writeTimeout time.Duration) Conn {
218
+	return &conn{
219
+		conn:         netConn,
220
+		bw:           bufio.NewWriter(netConn),
221
+		br:           bufio.NewReader(netConn),
222
+		readTimeout:  readTimeout,
223
+		writeTimeout: writeTimeout,
224
+	}
225
+}
226
+
227
+func (c *conn) Close() error {
228
+	c.mu.Lock()
229
+	err := c.err
230
+	if c.err == nil {
231
+		c.err = errors.New("redigo: closed")
232
+		err = c.conn.Close()
233
+	}
234
+	c.mu.Unlock()
235
+	return err
236
+}
237
+
238
+func (c *conn) fatal(err error) error {
239
+	c.mu.Lock()
240
+	if c.err == nil {
241
+		c.err = err
242
+		// Close connection to force errors on subsequent calls and to unblock
243
+		// other reader or writer.
244
+		c.conn.Close()
245
+	}
246
+	c.mu.Unlock()
247
+	return err
248
+}
249
+
250
+func (c *conn) Err() error {
251
+	c.mu.Lock()
252
+	err := c.err
253
+	c.mu.Unlock()
254
+	return err
255
+}
256
+
257
+func (c *conn) writeLen(prefix byte, n int) error {
258
+	c.lenScratch[len(c.lenScratch)-1] = '\n'
259
+	c.lenScratch[len(c.lenScratch)-2] = '\r'
260
+	i := len(c.lenScratch) - 3
261
+	for {
262
+		c.lenScratch[i] = byte('0' + n%10)
263
+		i -= 1
264
+		n = n / 10
265
+		if n == 0 {
266
+			break
267
+		}
268
+	}
269
+	c.lenScratch[i] = prefix
270
+	_, err := c.bw.Write(c.lenScratch[i:])
271
+	return err
272
+}
273
+
274
+func (c *conn) writeString(s string) error {
275
+	c.writeLen('$', len(s))
276
+	c.bw.WriteString(s)
277
+	_, err := c.bw.WriteString("\r\n")
278
+	return err
279
+}
280
+
281
+func (c *conn) writeBytes(p []byte) error {
282
+	c.writeLen('$', len(p))
283
+	c.bw.Write(p)
284
+	_, err := c.bw.WriteString("\r\n")
285
+	return err
286
+}
287
+
288
+func (c *conn) writeInt64(n int64) error {
289
+	return c.writeBytes(strconv.AppendInt(c.numScratch[:0], n, 10))
290
+}
291
+
292
+func (c *conn) writeFloat64(n float64) error {
293
+	return c.writeBytes(strconv.AppendFloat(c.numScratch[:0], n, 'g', -1, 64))
294
+}
295
+
296
+func (c *conn) writeCommand(cmd string, args []interface{}) (err error) {
297
+	c.writeLen('*', 1+len(args))
298
+	err = c.writeString(cmd)
299
+	for _, arg := range args {
300
+		if err != nil {
301
+			break
302
+		}
303
+		switch arg := arg.(type) {
304
+		case string:
305
+			err = c.writeString(arg)
306
+		case []byte:
307
+			err = c.writeBytes(arg)
308
+		case int:
309
+			err = c.writeInt64(int64(arg))
310
+		case int64:
311
+			err = c.writeInt64(arg)
312
+		case float64:
313
+			err = c.writeFloat64(arg)
314
+		case bool:
315
+			if arg {
316
+				err = c.writeString("1")
317
+			} else {
318
+				err = c.writeString("0")
319
+			}
320
+		case nil:
321
+			err = c.writeString("")
322
+		default:
323
+			var buf bytes.Buffer
324
+			fmt.Fprint(&buf, arg)
325
+			err = c.writeBytes(buf.Bytes())
326
+		}
327
+	}
328
+	return err
329
+}
330
+
331
+type protocolError string
332
+
333
+func (pe protocolError) Error() string {
334
+	return fmt.Sprintf("redigo: %s (possible server error or unsupported concurrent read by application)", string(pe))
335
+}
336
+
337
+func (c *conn) readLine() ([]byte, error) {
338
+	p, err := c.br.ReadSlice('\n')
339
+	if err == bufio.ErrBufferFull {
340
+		return nil, protocolError("long response line")
341
+	}
342
+	if err != nil {
343
+		return nil, err
344
+	}
345
+	i := len(p) - 2
346
+	if i < 0 || p[i] != '\r' {
347
+		return nil, protocolError("bad response line terminator")
348
+	}
349
+	return p[:i], nil
350
+}
351
+
352
+// parseLen parses bulk string and array lengths.
353
+func parseLen(p []byte) (int, error) {
354
+	if len(p) == 0 {
355
+		return -1, protocolError("malformed length")
356
+	}
357
+
358
+	if p[0] == '-' && len(p) == 2 && p[1] == '1' {
359
+		// handle $-1 and $-1 null replies.
360
+		return -1, nil
361
+	}
362
+
363
+	var n int
364
+	for _, b := range p {
365
+		n *= 10
366
+		if b < '0' || b > '9' {
367
+			return -1, protocolError("illegal bytes in length")
368
+		}
369
+		n += int(b - '0')
370
+	}
371
+
372
+	return n, nil
373
+}
374
+
375
+// parseInt parses an integer reply.
376
+func parseInt(p []byte) (interface{}, error) {
377
+	if len(p) == 0 {
378
+		return 0, protocolError("malformed integer")
379
+	}
380
+
381
+	var negate bool
382
+	if p[0] == '-' {
383
+		negate = true
384
+		p = p[1:]
385
+		if len(p) == 0 {
386
+			return 0, protocolError("malformed integer")
387
+		}
388
+	}
389
+
390
+	var n int64
391
+	for _, b := range p {
392
+		n *= 10
393
+		if b < '0' || b > '9' {
394
+			return 0, protocolError("illegal bytes in length")
395
+		}
396
+		n += int64(b - '0')
397
+	}
398
+
399
+	if negate {
400
+		n = -n
401
+	}
402
+	return n, nil
403
+}
404
+
405
+var (
406
+	okReply   interface{} = "OK"
407
+	pongReply interface{} = "PONG"
408
+)
409
+
410
+func (c *conn) readReply() (interface{}, error) {
411
+	line, err := c.readLine()
412
+	if err != nil {
413
+		return nil, err
414
+	}
415
+	if len(line) == 0 {
416
+		return nil, protocolError("short response line")
417
+	}
418
+	switch line[0] {
419
+	case '+':
420
+		switch {
421
+		case len(line) == 3 && line[1] == 'O' && line[2] == 'K':
422
+			// Avoid allocation for frequent "+OK" response.
423
+			return okReply, nil
424
+		case len(line) == 5 && line[1] == 'P' && line[2] == 'O' && line[3] == 'N' && line[4] == 'G':
425
+			// Avoid allocation in PING command benchmarks :)
426
+			return pongReply, nil
427
+		default:
428
+			return string(line[1:]), nil
429
+		}
430
+	case '-':
431
+		return Error(string(line[1:])), nil
432
+	case ':':
433
+		return parseInt(line[1:])
434
+	case '$':
435
+		n, err := parseLen(line[1:])
436
+		if n < 0 || err != nil {
437
+			return nil, err
438
+		}
439
+		p := make([]byte, n)
440
+		_, err = io.ReadFull(c.br, p)
441
+		if err != nil {
442
+			return nil, err
443
+		}
444
+		if line, err := c.readLine(); err != nil {
445
+			return nil, err
446
+		} else if len(line) != 0 {
447
+			return nil, protocolError("bad bulk string format")
448
+		}
449
+		return p, nil
450
+	case '*':
451
+		n, err := parseLen(line[1:])
452
+		if n < 0 || err != nil {
453
+			return nil, err
454
+		}
455
+		r := make([]interface{}, n)
456
+		for i := range r {
457
+			r[i], err = c.readReply()
458
+			if err != nil {
459
+				return nil, err
460
+			}
461
+		}
462
+		return r, nil
463
+	}
464
+	return nil, protocolError("unexpected response line")
465
+}
466
+
467
+func (c *conn) Send(cmd string, args ...interface{}) error {
468
+	c.mu.Lock()
469
+	c.pending += 1
470
+	c.mu.Unlock()
471
+	if c.writeTimeout != 0 {
472
+		c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
473
+	}
474
+	if err := c.writeCommand(cmd, args); err != nil {
475
+		return c.fatal(err)
476
+	}
477
+	return nil
478
+}
479
+
480
+func (c *conn) Flush() error {
481
+	if c.writeTimeout != 0 {
482
+		c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
483
+	}
484
+	if err := c.bw.Flush(); err != nil {
485
+		return c.fatal(err)
486
+	}
487
+	return nil
488
+}
489
+
490
+func (c *conn) Receive() (reply interface{}, err error) {
491
+	if c.readTimeout != 0 {
492
+		c.conn.SetReadDeadline(time.Now().Add(c.readTimeout))
493
+	}
494
+	if reply, err = c.readReply(); err != nil {
495
+		return nil, c.fatal(err)
496
+	}
497
+	// When using pub/sub, the number of receives can be greater than the
498
+	// number of sends. To enable normal use of the connection after
499
+	// unsubscribing from all channels, we do not decrement pending to a
500
+	// negative value.
501
+	//
502
+	// The pending field is decremented after the reply is read to handle the
503
+	// case where Receive is called before Send.
504
+	c.mu.Lock()
505
+	if c.pending > 0 {
506
+		c.pending -= 1
507
+	}
508
+	c.mu.Unlock()
509
+	if err, ok := reply.(Error); ok {
510
+		return nil, err
511
+	}
512
+	return
513
+}
514
+
515
+func (c *conn) Do(cmd string, args ...interface{}) (interface{}, error) {
516
+	c.mu.Lock()
517
+	pending := c.pending
518
+	c.pending = 0
519
+	c.mu.Unlock()
520
+
521
+	if cmd == "" && pending == 0 {
522
+		return nil, nil
523
+	}
524
+
525
+	if c.writeTimeout != 0 {
526
+		c.conn.SetWriteDeadline(time.Now().Add(c.writeTimeout))
527
+	}
528
+
529
+	if cmd != "" {
530
+		if err := c.writeCommand(cmd, args); err != nil {
531
+			return nil, c.fatal(err)
532
+		}
533
+	}
534
+
535
+	if err := c.bw.Flush(); err != nil {
536
+		return nil, c.fatal(err)
537
+	}
538
+
539
+	if c.readTimeout != 0 {
540
+		c.conn.SetReadDeadline(time.Now().Add(c.readTimeout))
541
+	}
542
+
543
+	if cmd == "" {
544
+		reply := make([]interface{}, pending)
545
+		for i := range reply {
546
+			r, e := c.readReply()
547
+			if e != nil {
548
+				return nil, c.fatal(e)
549
+			}
550
+			reply[i] = r
551
+		}
552
+		return reply, nil
553
+	}
554
+
555
+	var err error
556
+	var reply interface{}
557
+	for i := 0; i <= pending; i++ {
558
+		var e error
559
+		if reply, e = c.readReply(); e != nil {
560
+			return nil, c.fatal(e)
561
+		}
562
+		if e, ok := reply.(Error); ok && err == nil {
563
+			err = e
564
+		}
565
+	}
566
+	return reply, err
567
+}

+ 169
- 0
vendor/github.com/garyburd/redigo/redis/doc.go Bestand weergeven

@@ -0,0 +1,169 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+// Package redis is a client for the Redis database.
16
+//
17
+// The Redigo FAQ (https://github.com/garyburd/redigo/wiki/FAQ) contains more
18
+// documentation about this package.
19
+//
20
+// Connections
21
+//
22
+// The Conn interface is the primary interface for working with Redis.
23
+// Applications create connections by calling the Dial, DialWithTimeout or
24
+// NewConn functions. In the future, functions will be added for creating
25
+// sharded and other types of connections.
26
+//
27
+// The application must call the connection Close method when the application
28
+// is done with the connection.
29
+//
30
+// Executing Commands
31
+//
32
+// The Conn interface has a generic method for executing Redis commands:
33
+//
34
+//  Do(commandName string, args ...interface{}) (reply interface{}, err error)
35
+//
36
+// The Redis command reference (http://redis.io/commands) lists the available
37
+// commands. An example of using the Redis APPEND command is:
38
+//
39
+//  n, err := conn.Do("APPEND", "key", "value")
40
+//
41
+// The Do method converts command arguments to binary strings for transmission
42
+// to the server as follows:
43
+//
44
+//  Go Type                 Conversion
45
+//  []byte                  Sent as is
46
+//  string                  Sent as is
47
+//  int, int64              strconv.FormatInt(v)
48
+//  float64                 strconv.FormatFloat(v, 'g', -1, 64)
49
+//  bool                    true -> "1", false -> "0"
50
+//  nil                     ""
51
+//  all other types         fmt.Print(v)
52
+//
53
+// Redis command reply types are represented using the following Go types:
54
+//
55
+//  Redis type              Go type
56
+//  error                   redis.Error
57
+//  integer                 int64
58
+//  simple string           string
59
+//  bulk string             []byte or nil if value not present.
60
+//  array                   []interface{} or nil if value not present.
61
+//
62
+// Use type assertions or the reply helper functions to convert from
63
+// interface{} to the specific Go type for the command result.
64
+//
65
+// Pipelining
66
+//
67
+// Connections support pipelining using the Send, Flush and Receive methods.
68
+//
69
+//  Send(commandName string, args ...interface{}) error
70
+//  Flush() error
71
+//  Receive() (reply interface{}, err error)
72
+//
73
+// Send writes the command to the connection's output buffer. Flush flushes the
74
+// connection's output buffer to the server. Receive reads a single reply from
75
+// the server. The following example shows a simple pipeline.
76
+//
77
+//  c.Send("SET", "foo", "bar")
78
+//  c.Send("GET", "foo")
79
+//  c.Flush()
80
+//  c.Receive() // reply from SET
81
+//  v, err = c.Receive() // reply from GET
82
+//
83
+// The Do method combines the functionality of the Send, Flush and Receive
84
+// methods. The Do method starts by writing the command and flushing the output
85
+// buffer. Next, the Do method receives all pending replies including the reply
86
+// for the command just sent by Do. If any of the received replies is an error,
87
+// then Do returns the error. If there are no errors, then Do returns the last
88
+// reply. If the command argument to the Do method is "", then the Do method
89
+// will flush the output buffer and receive pending replies without sending a
90
+// command.
91
+//
92
+// Use the Send and Do methods to implement pipelined transactions.
93
+//
94
+//  c.Send("MULTI")
95
+//  c.Send("INCR", "foo")
96
+//  c.Send("INCR", "bar")
97
+//  r, err := c.Do("EXEC")
98
+//  fmt.Println(r) // prints [1, 1]
99
+//
100
+// Concurrency
101
+//
102
+// Connections do not support concurrent calls to the write methods (Send,
103
+// Flush) or concurrent calls to the read method (Receive). Connections do
104
+// allow a concurrent reader and writer.
105
+//
106
+// Because the Do method combines the functionality of Send, Flush and Receive,
107
+// the Do method cannot be called concurrently with the other methods.
108
+//
109
+// For full concurrent access to Redis, use the thread-safe Pool to get and
110
+// release connections from within a goroutine.
111
+//
112
+// Publish and Subscribe
113
+//
114
+// Use the Send, Flush and Receive methods to implement Pub/Sub subscribers.
115
+//
116
+//  c.Send("SUBSCRIBE", "example")
117
+//  c.Flush()
118
+//  for {
119
+//      reply, err := c.Receive()
120
+//      if err != nil {
121
+//          return err
122
+//      }
123
+//      // process pushed message
124
+//  }
125
+//
126
+// The PubSubConn type wraps a Conn with convenience methods for implementing
127
+// subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods
128
+// send and flush a subscription management command. The receive method
129
+// converts a pushed message to convenient types for use in a type switch.
130
+//
131
+//  psc := redis.PubSubConn{c}
132
+//  psc.Subscribe("example")
133
+//  for {
134
+//      switch v := psc.Receive().(type) {
135
+//      case redis.Message:
136
+//          fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
137
+//      case redis.Subscription:
138
+//          fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
139
+//      case error:
140
+//          return v
141
+//      }
142
+//  }
143
+//
144
+// Reply Helpers
145
+//
146
+// The Bool, Int, Bytes, String, Strings and Values functions convert a reply
147
+// to a value of a specific type. To allow convenient wrapping of calls to the
148
+// connection Do and Receive methods, the functions take a second argument of
149
+// type error.  If the error is non-nil, then the helper function returns the
150
+// error. If the error is nil, the function converts the reply to the specified
151
+// type:
152
+//
153
+//  exists, err := redis.Bool(c.Do("EXISTS", "foo"))
154
+//  if err != nil {
155
+//      // handle error return from c.Do or type conversion error.
156
+//  }
157
+//
158
+// The Scan function converts elements of a array reply to Go types:
159
+//
160
+//  var value1 int
161
+//  var value2 string
162
+//  reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
163
+//  if err != nil {
164
+//      // handle error
165
+//  }
166
+//   if _, err := redis.Scan(reply, &value1, &value2); err != nil {
167
+//      // handle error
168
+//  }
169
+package redis // import "github.com/garyburd/redigo/redis"

+ 117
- 0
vendor/github.com/garyburd/redigo/redis/log.go Bestand weergeven

@@ -0,0 +1,117 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import (
18
+	"bytes"
19
+	"fmt"
20
+	"log"
21
+)
22
+
23
+// NewLoggingConn returns a logging wrapper around a connection.
24
+func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn {
25
+	if prefix != "" {
26
+		prefix = prefix + "."
27
+	}
28
+	return &loggingConn{conn, logger, prefix}
29
+}
30
+
31
+type loggingConn struct {
32
+	Conn
33
+	logger *log.Logger
34
+	prefix string
35
+}
36
+
37
+func (c *loggingConn) Close() error {
38
+	err := c.Conn.Close()
39
+	var buf bytes.Buffer
40
+	fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err)
41
+	c.logger.Output(2, buf.String())
42
+	return err
43
+}
44
+
45
+func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) {
46
+	const chop = 32
47
+	switch v := v.(type) {
48
+	case []byte:
49
+		if len(v) > chop {
50
+			fmt.Fprintf(buf, "%q...", v[:chop])
51
+		} else {
52
+			fmt.Fprintf(buf, "%q", v)
53
+		}
54
+	case string:
55
+		if len(v) > chop {
56
+			fmt.Fprintf(buf, "%q...", v[:chop])
57
+		} else {
58
+			fmt.Fprintf(buf, "%q", v)
59
+		}
60
+	case []interface{}:
61
+		if len(v) == 0 {
62
+			buf.WriteString("[]")
63
+		} else {
64
+			sep := "["
65
+			fin := "]"
66
+			if len(v) > chop {
67
+				v = v[:chop]
68
+				fin = "...]"
69
+			}
70
+			for _, vv := range v {
71
+				buf.WriteString(sep)
72
+				c.printValue(buf, vv)
73
+				sep = ", "
74
+			}
75
+			buf.WriteString(fin)
76
+		}
77
+	default:
78
+		fmt.Fprint(buf, v)
79
+	}
80
+}
81
+
82
+func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) {
83
+	var buf bytes.Buffer
84
+	fmt.Fprintf(&buf, "%s%s(", c.prefix, method)
85
+	if method != "Receive" {
86
+		buf.WriteString(commandName)
87
+		for _, arg := range args {
88
+			buf.WriteString(", ")
89
+			c.printValue(&buf, arg)
90
+		}
91
+	}
92
+	buf.WriteString(") -> (")
93
+	if method != "Send" {
94
+		c.printValue(&buf, reply)
95
+		buf.WriteString(", ")
96
+	}
97
+	fmt.Fprintf(&buf, "%v)", err)
98
+	c.logger.Output(3, buf.String())
99
+}
100
+
101
+func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) {
102
+	reply, err := c.Conn.Do(commandName, args...)
103
+	c.print("Do", commandName, args, reply, err)
104
+	return reply, err
105
+}
106
+
107
+func (c *loggingConn) Send(commandName string, args ...interface{}) error {
108
+	err := c.Conn.Send(commandName, args...)
109
+	c.print("Send", commandName, args, nil, err)
110
+	return err
111
+}
112
+
113
+func (c *loggingConn) Receive() (interface{}, error) {
114
+	reply, err := c.Conn.Receive()
115
+	c.print("Receive", "", nil, reply, err)
116
+	return reply, err
117
+}

+ 393
- 0
vendor/github.com/garyburd/redigo/redis/pool.go Bestand weergeven

@@ -0,0 +1,393 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import (
18
+	"bytes"
19
+	"container/list"
20
+	"crypto/rand"
21
+	"crypto/sha1"
22
+	"errors"
23
+	"io"
24
+	"strconv"
25
+	"sync"
26
+	"time"
27
+
28
+	"github.com/garyburd/redigo/internal"
29
+)
30
+
31
+var nowFunc = time.Now // for testing
32
+
33
+// ErrPoolExhausted is returned from a pool connection method (Do, Send,
34
+// Receive, Flush, Err) when the maximum number of database connections in the
35
+// pool has been reached.
36
+var ErrPoolExhausted = errors.New("redigo: connection pool exhausted")
37
+
38
+var (
39
+	errPoolClosed = errors.New("redigo: connection pool closed")
40
+	errConnClosed = errors.New("redigo: connection closed")
41
+)
42
+
43
+// Pool maintains a pool of connections. The application calls the Get method
44
+// to get a connection from the pool and the connection's Close method to
45
+// return the connection's resources to the pool.
46
+//
47
+// The following example shows how to use a pool in a web application. The
48
+// application creates a pool at application startup and makes it available to
49
+// request handlers using a global variable.
50
+//
51
+//  func newPool(server, password string) *redis.Pool {
52
+//      return &redis.Pool{
53
+//          MaxIdle: 3,
54
+//          IdleTimeout: 240 * time.Second,
55
+//          Dial: func () (redis.Conn, error) {
56
+//              c, err := redis.Dial("tcp", server)
57
+//              if err != nil {
58
+//                  return nil, err
59
+//              }
60
+//              if _, err := c.Do("AUTH", password); err != nil {
61
+//                  c.Close()
62
+//                  return nil, err
63
+//              }
64
+//              return c, err
65
+//          },
66
+//          TestOnBorrow: func(c redis.Conn, t time.Time) error {
67
+//              _, err := c.Do("PING")
68
+//              return err
69
+//          },
70
+//      }
71
+//  }
72
+//
73
+//  var (
74
+//      pool *redis.Pool
75
+//      redisServer = flag.String("redisServer", ":6379", "")
76
+//      redisPassword = flag.String("redisPassword", "", "")
77
+//  )
78
+//
79
+//  func main() {
80
+//      flag.Parse()
81
+//      pool = newPool(*redisServer, *redisPassword)
82
+//      ...
83
+//  }
84
+//
85
+// A request handler gets a connection from the pool and closes the connection
86
+// when the handler is done:
87
+//
88
+//  func serveHome(w http.ResponseWriter, r *http.Request) {
89
+//      conn := pool.Get()
90
+//      defer conn.Close()
91
+//      ....
92
+//  }
93
+//
94
+type Pool struct {
95
+
96
+	// Dial is an application supplied function for creating and configuring a
97
+	// connection.
98
+	//
99
+	// The connection returned from Dial must not be in a special state
100
+	// (subscribed to pubsub channel, transaction started, ...).
101
+	Dial func() (Conn, error)
102
+
103
+	// TestOnBorrow is an optional application supplied function for checking
104
+	// the health of an idle connection before the connection is used again by
105
+	// the application. Argument t is the time that the connection was returned
106
+	// to the pool. If the function returns an error, then the connection is
107
+	// closed.
108
+	TestOnBorrow func(c Conn, t time.Time) error
109
+
110
+	// Maximum number of idle connections in the pool.
111
+	MaxIdle int
112
+
113
+	// Maximum number of connections allocated by the pool at a given time.
114
+	// When zero, there is no limit on the number of connections in the pool.
115
+	MaxActive int
116
+
117
+	// Close connections after remaining idle for this duration. If the value
118
+	// is zero, then idle connections are not closed. Applications should set
119
+	// the timeout to a value less than the server's timeout.
120
+	IdleTimeout time.Duration
121
+
122
+	// If Wait is true and the pool is at the MaxActive limit, then Get() waits
123
+	// for a connection to be returned to the pool before returning.
124
+	Wait bool
125
+
126
+	// mu protects fields defined below.
127
+	mu     sync.Mutex
128
+	cond   *sync.Cond
129
+	closed bool
130
+	active int
131
+
132
+	// Stack of idleConn with most recently used at the front.
133
+	idle list.List
134
+}
135
+
136
+type idleConn struct {
137
+	c Conn
138
+	t time.Time
139
+}
140
+
141
+// NewPool creates a new pool.
142
+//
143
+// Deprecated: Initialize the Pool directory as shown in the example.
144
+func NewPool(newFn func() (Conn, error), maxIdle int) *Pool {
145
+	return &Pool{Dial: newFn, MaxIdle: maxIdle}
146
+}
147
+
148
+// Get gets a connection. The application must close the returned connection.
149
+// This method always returns a valid connection so that applications can defer
150
+// error handling to the first use of the connection. If there is an error
151
+// getting an underlying connection, then the connection Err, Do, Send, Flush
152
+// and Receive methods return that error.
153
+func (p *Pool) Get() Conn {
154
+	c, err := p.get()
155
+	if err != nil {
156
+		return errorConnection{err}
157
+	}
158
+	return &pooledConnection{p: p, c: c}
159
+}
160
+
161
+// ActiveCount returns the number of active connections in the pool.
162
+func (p *Pool) ActiveCount() int {
163
+	p.mu.Lock()
164
+	active := p.active
165
+	p.mu.Unlock()
166
+	return active
167
+}
168
+
169
+// Close releases the resources used by the pool.
170
+func (p *Pool) Close() error {
171
+	p.mu.Lock()
172
+	idle := p.idle
173
+	p.idle.Init()
174
+	p.closed = true
175
+	p.active -= idle.Len()
176
+	if p.cond != nil {
177
+		p.cond.Broadcast()
178
+	}
179
+	p.mu.Unlock()
180
+	for e := idle.Front(); e != nil; e = e.Next() {
181
+		e.Value.(idleConn).c.Close()
182
+	}
183
+	return nil
184
+}
185
+
186
+// release decrements the active count and signals waiters. The caller must
187
+// hold p.mu during the call.
188
+func (p *Pool) release() {
189
+	p.active -= 1
190
+	if p.cond != nil {
191
+		p.cond.Signal()
192
+	}
193
+}
194
+
195
+// get prunes stale connections and returns a connection from the idle list or
196
+// creates a new connection.
197
+func (p *Pool) get() (Conn, error) {
198
+	p.mu.Lock()
199
+
200
+	// Prune stale connections.
201
+
202
+	if timeout := p.IdleTimeout; timeout > 0 {
203
+		for i, n := 0, p.idle.Len(); i < n; i++ {
204
+			e := p.idle.Back()
205
+			if e == nil {
206
+				break
207
+			}
208
+			ic := e.Value.(idleConn)
209
+			if ic.t.Add(timeout).After(nowFunc()) {
210
+				break
211
+			}
212
+			p.idle.Remove(e)
213
+			p.release()
214
+			p.mu.Unlock()
215
+			ic.c.Close()
216
+			p.mu.Lock()
217
+		}
218
+	}
219
+
220
+	for {
221
+
222
+		// Get idle connection.
223
+
224
+		for i, n := 0, p.idle.Len(); i < n; i++ {
225
+			e := p.idle.Front()
226
+			if e == nil {
227
+				break
228
+			}
229
+			ic := e.Value.(idleConn)
230
+			p.idle.Remove(e)
231
+			test := p.TestOnBorrow
232
+			p.mu.Unlock()
233
+			if test == nil || test(ic.c, ic.t) == nil {
234
+				return ic.c, nil
235
+			}
236
+			ic.c.Close()
237
+			p.mu.Lock()
238
+			p.release()
239
+		}
240
+
241
+		// Check for pool closed before dialing a new connection.
242
+
243
+		if p.closed {
244
+			p.mu.Unlock()
245
+			return nil, errors.New("redigo: get on closed pool")
246
+		}
247
+
248
+		// Dial new connection if under limit.
249
+
250
+		if p.MaxActive == 0 || p.active < p.MaxActive {
251
+			dial := p.Dial
252
+			p.active += 1
253
+			p.mu.Unlock()
254
+			c, err := dial()
255
+			if err != nil {
256
+				p.mu.Lock()
257
+				p.release()
258
+				p.mu.Unlock()
259
+				c = nil
260
+			}
261
+			return c, err
262
+		}
263
+
264
+		if !p.Wait {
265
+			p.mu.Unlock()
266
+			return nil, ErrPoolExhausted
267
+		}
268
+
269
+		if p.cond == nil {
270
+			p.cond = sync.NewCond(&p.mu)
271
+		}
272
+		p.cond.Wait()
273
+	}
274
+}
275
+
276
+func (p *Pool) put(c Conn, forceClose bool) error {
277
+	err := c.Err()
278
+	p.mu.Lock()
279
+	if !p.closed && err == nil && !forceClose {
280
+		p.idle.PushFront(idleConn{t: nowFunc(), c: c})
281
+		if p.idle.Len() > p.MaxIdle {
282
+			c = p.idle.Remove(p.idle.Back()).(idleConn).c
283
+		} else {
284
+			c = nil
285
+		}
286
+	}
287
+
288
+	if c == nil {
289
+		if p.cond != nil {
290
+			p.cond.Signal()
291
+		}
292
+		p.mu.Unlock()
293
+		return nil
294
+	}
295
+
296
+	p.release()
297
+	p.mu.Unlock()
298
+	return c.Close()
299
+}
300
+
301
+type pooledConnection struct {
302
+	p     *Pool
303
+	c     Conn
304
+	state int
305
+}
306
+
307
+var (
308
+	sentinel     []byte
309
+	sentinelOnce sync.Once
310
+)
311
+
312
+func initSentinel() {
313
+	p := make([]byte, 64)
314
+	if _, err := rand.Read(p); err == nil {
315
+		sentinel = p
316
+	} else {
317
+		h := sha1.New()
318
+		io.WriteString(h, "Oops, rand failed. Use time instead.")
319
+		io.WriteString(h, strconv.FormatInt(time.Now().UnixNano(), 10))
320
+		sentinel = h.Sum(nil)
321
+	}
322
+}
323
+
324
+func (pc *pooledConnection) Close() error {
325
+	c := pc.c
326
+	if _, ok := c.(errorConnection); ok {
327
+		return nil
328
+	}
329
+	pc.c = errorConnection{errConnClosed}
330
+
331
+	if pc.state&internal.MultiState != 0 {
332
+		c.Send("DISCARD")
333
+		pc.state &^= (internal.MultiState | internal.WatchState)
334
+	} else if pc.state&internal.WatchState != 0 {
335
+		c.Send("UNWATCH")
336
+		pc.state &^= internal.WatchState
337
+	}
338
+	if pc.state&internal.SubscribeState != 0 {
339
+		c.Send("UNSUBSCRIBE")
340
+		c.Send("PUNSUBSCRIBE")
341
+		// To detect the end of the message stream, ask the server to echo
342
+		// a sentinel value and read until we see that value.
343
+		sentinelOnce.Do(initSentinel)
344
+		c.Send("ECHO", sentinel)
345
+		c.Flush()
346
+		for {
347
+			p, err := c.Receive()
348
+			if err != nil {
349
+				break
350
+			}
351
+			if p, ok := p.([]byte); ok && bytes.Equal(p, sentinel) {
352
+				pc.state &^= internal.SubscribeState
353
+				break
354
+			}
355
+		}
356
+	}
357
+	c.Do("")
358
+	pc.p.put(c, pc.state != 0)
359
+	return nil
360
+}
361
+
362
+func (pc *pooledConnection) Err() error {
363
+	return pc.c.Err()
364
+}
365
+
366
+func (pc *pooledConnection) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
367
+	ci := internal.LookupCommandInfo(commandName)
368
+	pc.state = (pc.state | ci.Set) &^ ci.Clear
369
+	return pc.c.Do(commandName, args...)
370
+}
371
+
372
+func (pc *pooledConnection) Send(commandName string, args ...interface{}) error {
373
+	ci := internal.LookupCommandInfo(commandName)
374
+	pc.state = (pc.state | ci.Set) &^ ci.Clear
375
+	return pc.c.Send(commandName, args...)
376
+}
377
+
378
+func (pc *pooledConnection) Flush() error {
379
+	return pc.c.Flush()
380
+}
381
+
382
+func (pc *pooledConnection) Receive() (reply interface{}, err error) {
383
+	return pc.c.Receive()
384
+}
385
+
386
+type errorConnection struct{ err error }
387
+
388
+func (ec errorConnection) Do(string, ...interface{}) (interface{}, error) { return nil, ec.err }
389
+func (ec errorConnection) Send(string, ...interface{}) error              { return ec.err }
390
+func (ec errorConnection) Err() error                                     { return ec.err }
391
+func (ec errorConnection) Close() error                                   { return ec.err }
392
+func (ec errorConnection) Flush() error                                   { return ec.err }
393
+func (ec errorConnection) Receive() (interface{}, error)                  { return nil, ec.err }

+ 144
- 0
vendor/github.com/garyburd/redigo/redis/pubsub.go Bestand weergeven

@@ -0,0 +1,144 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import "errors"
18
+
19
+// Subscription represents a subscribe or unsubscribe notification.
20
+type Subscription struct {
21
+
22
+	// Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe"
23
+	Kind string
24
+
25
+	// The channel that was changed.
26
+	Channel string
27
+
28
+	// The current number of subscriptions for connection.
29
+	Count int
30
+}
31
+
32
+// Message represents a message notification.
33
+type Message struct {
34
+
35
+	// The originating channel.
36
+	Channel string
37
+
38
+	// The message data.
39
+	Data []byte
40
+}
41
+
42
+// PMessage represents a pmessage notification.
43
+type PMessage struct {
44
+
45
+	// The matched pattern.
46
+	Pattern string
47
+
48
+	// The originating channel.
49
+	Channel string
50
+
51
+	// The message data.
52
+	Data []byte
53
+}
54
+
55
+// Pong represents a pubsub pong notification.
56
+type Pong struct {
57
+	Data string
58
+}
59
+
60
+// PubSubConn wraps a Conn with convenience methods for subscribers.
61
+type PubSubConn struct {
62
+	Conn Conn
63
+}
64
+
65
+// Close closes the connection.
66
+func (c PubSubConn) Close() error {
67
+	return c.Conn.Close()
68
+}
69
+
70
+// Subscribe subscribes the connection to the specified channels.
71
+func (c PubSubConn) Subscribe(channel ...interface{}) error {
72
+	c.Conn.Send("SUBSCRIBE", channel...)
73
+	return c.Conn.Flush()
74
+}
75
+
76
+// PSubscribe subscribes the connection to the given patterns.
77
+func (c PubSubConn) PSubscribe(channel ...interface{}) error {
78
+	c.Conn.Send("PSUBSCRIBE", channel...)
79
+	return c.Conn.Flush()
80
+}
81
+
82
+// Unsubscribe unsubscribes the connection from the given channels, or from all
83
+// of them if none is given.
84
+func (c PubSubConn) Unsubscribe(channel ...interface{}) error {
85
+	c.Conn.Send("UNSUBSCRIBE", channel...)
86
+	return c.Conn.Flush()
87
+}
88
+
89
+// PUnsubscribe unsubscribes the connection from the given patterns, or from all
90
+// of them if none is given.
91
+func (c PubSubConn) PUnsubscribe(channel ...interface{}) error {
92
+	c.Conn.Send("PUNSUBSCRIBE", channel...)
93
+	return c.Conn.Flush()
94
+}
95
+
96
+// Ping sends a PING to the server with the specified data.
97
+func (c PubSubConn) Ping(data string) error {
98
+	c.Conn.Send("PING", data)
99
+	return c.Conn.Flush()
100
+}
101
+
102
+// Receive returns a pushed message as a Subscription, Message, PMessage, Pong
103
+// or error. The return value is intended to be used directly in a type switch
104
+// as illustrated in the PubSubConn example.
105
+func (c PubSubConn) Receive() interface{} {
106
+	reply, err := Values(c.Conn.Receive())
107
+	if err != nil {
108
+		return err
109
+	}
110
+
111
+	var kind string
112
+	reply, err = Scan(reply, &kind)
113
+	if err != nil {
114
+		return err
115
+	}
116
+
117
+	switch kind {
118
+	case "message":
119
+		var m Message
120
+		if _, err := Scan(reply, &m.Channel, &m.Data); err != nil {
121
+			return err
122
+		}
123
+		return m
124
+	case "pmessage":
125
+		var pm PMessage
126
+		if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil {
127
+			return err
128
+		}
129
+		return pm
130
+	case "subscribe", "psubscribe", "unsubscribe", "punsubscribe":
131
+		s := Subscription{Kind: kind}
132
+		if _, err := Scan(reply, &s.Channel, &s.Count); err != nil {
133
+			return err
134
+		}
135
+		return s
136
+	case "pong":
137
+		var p Pong
138
+		if _, err := Scan(reply, &p.Data); err != nil {
139
+			return err
140
+		}
141
+		return p
142
+	}
143
+	return errors.New("redigo: unknown pubsub notification")
144
+}

+ 44
- 0
vendor/github.com/garyburd/redigo/redis/redis.go Bestand weergeven

@@ -0,0 +1,44 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+// Error represents an error returned in a command reply.
18
+type Error string
19
+
20
+func (err Error) Error() string { return string(err) }
21
+
22
+// Conn represents a connection to a Redis server.
23
+type Conn interface {
24
+	// Close closes the connection.
25
+	Close() error
26
+
27
+	// Err returns a non-nil value if the connection is broken. The returned
28
+	// value is either the first non-nil value returned from the underlying
29
+	// network connection or a protocol parsing error. Applications should
30
+	// close broken connections.
31
+	Err() error
32
+
33
+	// Do sends a command to the server and returns the received reply.
34
+	Do(commandName string, args ...interface{}) (reply interface{}, err error)
35
+
36
+	// Send writes the command to the client's output buffer.
37
+	Send(commandName string, args ...interface{}) error
38
+
39
+	// Flush flushes the output buffer to the Redis server.
40
+	Flush() error
41
+
42
+	// Receive receives a single reply from the Redis server
43
+	Receive() (reply interface{}, err error)
44
+}

+ 393
- 0
vendor/github.com/garyburd/redigo/redis/reply.go Bestand weergeven

@@ -0,0 +1,393 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import (
18
+	"errors"
19
+	"fmt"
20
+	"strconv"
21
+)
22
+
23
+// ErrNil indicates that a reply value is nil.
24
+var ErrNil = errors.New("redigo: nil returned")
25
+
26
+// Int is a helper that converts a command reply to an integer. If err is not
27
+// equal to nil, then Int returns 0, err. Otherwise, Int converts the
28
+// reply to an int as follows:
29
+//
30
+//  Reply type    Result
31
+//  integer       int(reply), nil
32
+//  bulk string   parsed reply, nil
33
+//  nil           0, ErrNil
34
+//  other         0, error
35
+func Int(reply interface{}, err error) (int, error) {
36
+	if err != nil {
37
+		return 0, err
38
+	}
39
+	switch reply := reply.(type) {
40
+	case int64:
41
+		x := int(reply)
42
+		if int64(x) != reply {
43
+			return 0, strconv.ErrRange
44
+		}
45
+		return x, nil
46
+	case []byte:
47
+		n, err := strconv.ParseInt(string(reply), 10, 0)
48
+		return int(n), err
49
+	case nil:
50
+		return 0, ErrNil
51
+	case Error:
52
+		return 0, reply
53
+	}
54
+	return 0, fmt.Errorf("redigo: unexpected type for Int, got type %T", reply)
55
+}
56
+
57
+// Int64 is a helper that converts a command reply to 64 bit integer. If err is
58
+// not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the
59
+// reply to an int64 as follows:
60
+//
61
+//  Reply type    Result
62
+//  integer       reply, nil
63
+//  bulk string   parsed reply, nil
64
+//  nil           0, ErrNil
65
+//  other         0, error
66
+func Int64(reply interface{}, err error) (int64, error) {
67
+	if err != nil {
68
+		return 0, err
69
+	}
70
+	switch reply := reply.(type) {
71
+	case int64:
72
+		return reply, nil
73
+	case []byte:
74
+		n, err := strconv.ParseInt(string(reply), 10, 64)
75
+		return n, err
76
+	case nil:
77
+		return 0, ErrNil
78
+	case Error:
79
+		return 0, reply
80
+	}
81
+	return 0, fmt.Errorf("redigo: unexpected type for Int64, got type %T", reply)
82
+}
83
+
84
+var errNegativeInt = errors.New("redigo: unexpected value for Uint64")
85
+
86
+// Uint64 is a helper that converts a command reply to 64 bit integer. If err is
87
+// not equal to nil, then Int returns 0, err. Otherwise, Int64 converts the
88
+// reply to an int64 as follows:
89
+//
90
+//  Reply type    Result
91
+//  integer       reply, nil
92
+//  bulk string   parsed reply, nil
93
+//  nil           0, ErrNil
94
+//  other         0, error
95
+func Uint64(reply interface{}, err error) (uint64, error) {
96
+	if err != nil {
97
+		return 0, err
98
+	}
99
+	switch reply := reply.(type) {
100
+	case int64:
101
+		if reply < 0 {
102
+			return 0, errNegativeInt
103
+		}
104
+		return uint64(reply), nil
105
+	case []byte:
106
+		n, err := strconv.ParseUint(string(reply), 10, 64)
107
+		return n, err
108
+	case nil:
109
+		return 0, ErrNil
110
+	case Error:
111
+		return 0, reply
112
+	}
113
+	return 0, fmt.Errorf("redigo: unexpected type for Uint64, got type %T", reply)
114
+}
115
+
116
+// Float64 is a helper that converts a command reply to 64 bit float. If err is
117
+// not equal to nil, then Float64 returns 0, err. Otherwise, Float64 converts
118
+// the reply to an int as follows:
119
+//
120
+//  Reply type    Result
121
+//  bulk string   parsed reply, nil
122
+//  nil           0, ErrNil
123
+//  other         0, error
124
+func Float64(reply interface{}, err error) (float64, error) {
125
+	if err != nil {
126
+		return 0, err
127
+	}
128
+	switch reply := reply.(type) {
129
+	case []byte:
130
+		n, err := strconv.ParseFloat(string(reply), 64)
131
+		return n, err
132
+	case nil:
133
+		return 0, ErrNil
134
+	case Error:
135
+		return 0, reply
136
+	}
137
+	return 0, fmt.Errorf("redigo: unexpected type for Float64, got type %T", reply)
138
+}
139
+
140
+// String is a helper that converts a command reply to a string. If err is not
141
+// equal to nil, then String returns "", err. Otherwise String converts the
142
+// reply to a string as follows:
143
+//
144
+//  Reply type      Result
145
+//  bulk string     string(reply), nil
146
+//  simple string   reply, nil
147
+//  nil             "",  ErrNil
148
+//  other           "",  error
149
+func String(reply interface{}, err error) (string, error) {
150
+	if err != nil {
151
+		return "", err
152
+	}
153
+	switch reply := reply.(type) {
154
+	case []byte:
155
+		return string(reply), nil
156
+	case string:
157
+		return reply, nil
158
+	case nil:
159
+		return "", ErrNil
160
+	case Error:
161
+		return "", reply
162
+	}
163
+	return "", fmt.Errorf("redigo: unexpected type for String, got type %T", reply)
164
+}
165
+
166
+// Bytes is a helper that converts a command reply to a slice of bytes. If err
167
+// is not equal to nil, then Bytes returns nil, err. Otherwise Bytes converts
168
+// the reply to a slice of bytes as follows:
169
+//
170
+//  Reply type      Result
171
+//  bulk string     reply, nil
172
+//  simple string   []byte(reply), nil
173
+//  nil             nil, ErrNil
174
+//  other           nil, error
175
+func Bytes(reply interface{}, err error) ([]byte, error) {
176
+	if err != nil {
177
+		return nil, err
178
+	}
179
+	switch reply := reply.(type) {
180
+	case []byte:
181
+		return reply, nil
182
+	case string:
183
+		return []byte(reply), nil
184
+	case nil:
185
+		return nil, ErrNil
186
+	case Error:
187
+		return nil, reply
188
+	}
189
+	return nil, fmt.Errorf("redigo: unexpected type for Bytes, got type %T", reply)
190
+}
191
+
192
+// Bool is a helper that converts a command reply to a boolean. If err is not
193
+// equal to nil, then Bool returns false, err. Otherwise Bool converts the
194
+// reply to boolean as follows:
195
+//
196
+//  Reply type      Result
197
+//  integer         value != 0, nil
198
+//  bulk string     strconv.ParseBool(reply)
199
+//  nil             false, ErrNil
200
+//  other           false, error
201
+func Bool(reply interface{}, err error) (bool, error) {
202
+	if err != nil {
203
+		return false, err
204
+	}
205
+	switch reply := reply.(type) {
206
+	case int64:
207
+		return reply != 0, nil
208
+	case []byte:
209
+		return strconv.ParseBool(string(reply))
210
+	case nil:
211
+		return false, ErrNil
212
+	case Error:
213
+		return false, reply
214
+	}
215
+	return false, fmt.Errorf("redigo: unexpected type for Bool, got type %T", reply)
216
+}
217
+
218
+// MultiBulk is a helper that converts an array command reply to a []interface{}.
219
+//
220
+// Deprecated: Use Values instead.
221
+func MultiBulk(reply interface{}, err error) ([]interface{}, error) { return Values(reply, err) }
222
+
223
+// Values is a helper that converts an array command reply to a []interface{}.
224
+// If err is not equal to nil, then Values returns nil, err. Otherwise, Values
225
+// converts the reply as follows:
226
+//
227
+//  Reply type      Result
228
+//  array           reply, nil
229
+//  nil             nil, ErrNil
230
+//  other           nil, error
231
+func Values(reply interface{}, err error) ([]interface{}, error) {
232
+	if err != nil {
233
+		return nil, err
234
+	}
235
+	switch reply := reply.(type) {
236
+	case []interface{}:
237
+		return reply, nil
238
+	case nil:
239
+		return nil, ErrNil
240
+	case Error:
241
+		return nil, reply
242
+	}
243
+	return nil, fmt.Errorf("redigo: unexpected type for Values, got type %T", reply)
244
+}
245
+
246
+// Strings is a helper that converts an array command reply to a []string. If
247
+// err is not equal to nil, then Strings returns nil, err. Nil array items are
248
+// converted to "" in the output slice. Strings returns an error if an array
249
+// item is not a bulk string or nil.
250
+func Strings(reply interface{}, err error) ([]string, error) {
251
+	if err != nil {
252
+		return nil, err
253
+	}
254
+	switch reply := reply.(type) {
255
+	case []interface{}:
256
+		result := make([]string, len(reply))
257
+		for i := range reply {
258
+			if reply[i] == nil {
259
+				continue
260
+			}
261
+			p, ok := reply[i].([]byte)
262
+			if !ok {
263
+				return nil, fmt.Errorf("redigo: unexpected element type for Strings, got type %T", reply[i])
264
+			}
265
+			result[i] = string(p)
266
+		}
267
+		return result, nil
268
+	case nil:
269
+		return nil, ErrNil
270
+	case Error:
271
+		return nil, reply
272
+	}
273
+	return nil, fmt.Errorf("redigo: unexpected type for Strings, got type %T", reply)
274
+}
275
+
276
+// ByteSlices is a helper that converts an array command reply to a [][]byte.
277
+// If err is not equal to nil, then ByteSlices returns nil, err. Nil array
278
+// items are stay nil. ByteSlices returns an error if an array item is not a
279
+// bulk string or nil.
280
+func ByteSlices(reply interface{}, err error) ([][]byte, error) {
281
+	if err != nil {
282
+		return nil, err
283
+	}
284
+	switch reply := reply.(type) {
285
+	case []interface{}:
286
+		result := make([][]byte, len(reply))
287
+		for i := range reply {
288
+			if reply[i] == nil {
289
+				continue
290
+			}
291
+			p, ok := reply[i].([]byte)
292
+			if !ok {
293
+				return nil, fmt.Errorf("redigo: unexpected element type for ByteSlices, got type %T", reply[i])
294
+			}
295
+			result[i] = p
296
+		}
297
+		return result, nil
298
+	case nil:
299
+		return nil, ErrNil
300
+	case Error:
301
+		return nil, reply
302
+	}
303
+	return nil, fmt.Errorf("redigo: unexpected type for ByteSlices, got type %T", reply)
304
+}
305
+
306
+// Ints is a helper that converts an array command reply to a []int. If
307
+// err is not equal to nil, then Ints returns nil, err.
308
+func Ints(reply interface{}, err error) ([]int, error) {
309
+	var ints []int
310
+	values, err := Values(reply, err)
311
+	if err != nil {
312
+		return ints, err
313
+	}
314
+	if err := ScanSlice(values, &ints); err != nil {
315
+		return ints, err
316
+	}
317
+	return ints, nil
318
+}
319
+
320
+// StringMap is a helper that converts an array of strings (alternating key, value)
321
+// into a map[string]string. The HGETALL and CONFIG GET commands return replies in this format.
322
+// Requires an even number of values in result.
323
+func StringMap(result interface{}, err error) (map[string]string, error) {
324
+	values, err := Values(result, err)
325
+	if err != nil {
326
+		return nil, err
327
+	}
328
+	if len(values)%2 != 0 {
329
+		return nil, errors.New("redigo: StringMap expects even number of values result")
330
+	}
331
+	m := make(map[string]string, len(values)/2)
332
+	for i := 0; i < len(values); i += 2 {
333
+		key, okKey := values[i].([]byte)
334
+		value, okValue := values[i+1].([]byte)
335
+		if !okKey || !okValue {
336
+			return nil, errors.New("redigo: ScanMap key not a bulk string value")
337
+		}
338
+		m[string(key)] = string(value)
339
+	}
340
+	return m, nil
341
+}
342
+
343
+// IntMap is a helper that converts an array of strings (alternating key, value)
344
+// into a map[string]int. The HGETALL commands return replies in this format.
345
+// Requires an even number of values in result.
346
+func IntMap(result interface{}, err error) (map[string]int, error) {
347
+	values, err := Values(result, err)
348
+	if err != nil {
349
+		return nil, err
350
+	}
351
+	if len(values)%2 != 0 {
352
+		return nil, errors.New("redigo: IntMap expects even number of values result")
353
+	}
354
+	m := make(map[string]int, len(values)/2)
355
+	for i := 0; i < len(values); i += 2 {
356
+		key, ok := values[i].([]byte)
357
+		if !ok {
358
+			return nil, errors.New("redigo: ScanMap key not a bulk string value")
359
+		}
360
+		value, err := Int(values[i+1], nil)
361
+		if err != nil {
362
+			return nil, err
363
+		}
364
+		m[string(key)] = value
365
+	}
366
+	return m, nil
367
+}
368
+
369
+// Int64Map is a helper that converts an array of strings (alternating key, value)
370
+// into a map[string]int64. The HGETALL commands return replies in this format.
371
+// Requires an even number of values in result.
372
+func Int64Map(result interface{}, err error) (map[string]int64, error) {
373
+	values, err := Values(result, err)
374
+	if err != nil {
375
+		return nil, err
376
+	}
377
+	if len(values)%2 != 0 {
378
+		return nil, errors.New("redigo: Int64Map expects even number of values result")
379
+	}
380
+	m := make(map[string]int64, len(values)/2)
381
+	for i := 0; i < len(values); i += 2 {
382
+		key, ok := values[i].([]byte)
383
+		if !ok {
384
+			return nil, errors.New("redigo: ScanMap key not a bulk string value")
385
+		}
386
+		value, err := Int64(values[i+1], nil)
387
+		if err != nil {
388
+			return nil, err
389
+		}
390
+		m[string(key)] = value
391
+	}
392
+	return m, nil
393
+}

+ 555
- 0
vendor/github.com/garyburd/redigo/redis/scan.go Bestand weergeven

@@ -0,0 +1,555 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import (
18
+	"errors"
19
+	"fmt"
20
+	"reflect"
21
+	"strconv"
22
+	"strings"
23
+	"sync"
24
+)
25
+
26
+func ensureLen(d reflect.Value, n int) {
27
+	if n > d.Cap() {
28
+		d.Set(reflect.MakeSlice(d.Type(), n, n))
29
+	} else {
30
+		d.SetLen(n)
31
+	}
32
+}
33
+
34
+func cannotConvert(d reflect.Value, s interface{}) error {
35
+	var sname string
36
+	switch s.(type) {
37
+	case string:
38
+		sname = "Redis simple string"
39
+	case Error:
40
+		sname = "Redis error"
41
+	case int64:
42
+		sname = "Redis integer"
43
+	case []byte:
44
+		sname = "Redis bulk string"
45
+	case []interface{}:
46
+		sname = "Redis array"
47
+	default:
48
+		sname = reflect.TypeOf(s).String()
49
+	}
50
+	return fmt.Errorf("cannot convert from %s to %s", sname, d.Type())
51
+}
52
+
53
+func convertAssignBulkString(d reflect.Value, s []byte) (err error) {
54
+	switch d.Type().Kind() {
55
+	case reflect.Float32, reflect.Float64:
56
+		var x float64
57
+		x, err = strconv.ParseFloat(string(s), d.Type().Bits())
58
+		d.SetFloat(x)
59
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
60
+		var x int64
61
+		x, err = strconv.ParseInt(string(s), 10, d.Type().Bits())
62
+		d.SetInt(x)
63
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
64
+		var x uint64
65
+		x, err = strconv.ParseUint(string(s), 10, d.Type().Bits())
66
+		d.SetUint(x)
67
+	case reflect.Bool:
68
+		var x bool
69
+		x, err = strconv.ParseBool(string(s))
70
+		d.SetBool(x)
71
+	case reflect.String:
72
+		d.SetString(string(s))
73
+	case reflect.Slice:
74
+		if d.Type().Elem().Kind() != reflect.Uint8 {
75
+			err = cannotConvert(d, s)
76
+		} else {
77
+			d.SetBytes(s)
78
+		}
79
+	default:
80
+		err = cannotConvert(d, s)
81
+	}
82
+	return
83
+}
84
+
85
+func convertAssignInt(d reflect.Value, s int64) (err error) {
86
+	switch d.Type().Kind() {
87
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
88
+		d.SetInt(s)
89
+		if d.Int() != s {
90
+			err = strconv.ErrRange
91
+			d.SetInt(0)
92
+		}
93
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
94
+		if s < 0 {
95
+			err = strconv.ErrRange
96
+		} else {
97
+			x := uint64(s)
98
+			d.SetUint(x)
99
+			if d.Uint() != x {
100
+				err = strconv.ErrRange
101
+				d.SetUint(0)
102
+			}
103
+		}
104
+	case reflect.Bool:
105
+		d.SetBool(s != 0)
106
+	default:
107
+		err = cannotConvert(d, s)
108
+	}
109
+	return
110
+}
111
+
112
+func convertAssignValue(d reflect.Value, s interface{}) (err error) {
113
+	switch s := s.(type) {
114
+	case []byte:
115
+		err = convertAssignBulkString(d, s)
116
+	case int64:
117
+		err = convertAssignInt(d, s)
118
+	default:
119
+		err = cannotConvert(d, s)
120
+	}
121
+	return err
122
+}
123
+
124
+func convertAssignArray(d reflect.Value, s []interface{}) error {
125
+	if d.Type().Kind() != reflect.Slice {
126
+		return cannotConvert(d, s)
127
+	}
128
+	ensureLen(d, len(s))
129
+	for i := 0; i < len(s); i++ {
130
+		if err := convertAssignValue(d.Index(i), s[i]); err != nil {
131
+			return err
132
+		}
133
+	}
134
+	return nil
135
+}
136
+
137
+func convertAssign(d interface{}, s interface{}) (err error) {
138
+	// Handle the most common destination types using type switches and
139
+	// fall back to reflection for all other types.
140
+	switch s := s.(type) {
141
+	case nil:
142
+		// ingore
143
+	case []byte:
144
+		switch d := d.(type) {
145
+		case *string:
146
+			*d = string(s)
147
+		case *int:
148
+			*d, err = strconv.Atoi(string(s))
149
+		case *bool:
150
+			*d, err = strconv.ParseBool(string(s))
151
+		case *[]byte:
152
+			*d = s
153
+		case *interface{}:
154
+			*d = s
155
+		case nil:
156
+			// skip value
157
+		default:
158
+			if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
159
+				err = cannotConvert(d, s)
160
+			} else {
161
+				err = convertAssignBulkString(d.Elem(), s)
162
+			}
163
+		}
164
+	case int64:
165
+		switch d := d.(type) {
166
+		case *int:
167
+			x := int(s)
168
+			if int64(x) != s {
169
+				err = strconv.ErrRange
170
+				x = 0
171
+			}
172
+			*d = x
173
+		case *bool:
174
+			*d = s != 0
175
+		case *interface{}:
176
+			*d = s
177
+		case nil:
178
+			// skip value
179
+		default:
180
+			if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
181
+				err = cannotConvert(d, s)
182
+			} else {
183
+				err = convertAssignInt(d.Elem(), s)
184
+			}
185
+		}
186
+	case string:
187
+		switch d := d.(type) {
188
+		case *string:
189
+			*d = string(s)
190
+		default:
191
+			err = cannotConvert(reflect.ValueOf(d), s)
192
+		}
193
+	case []interface{}:
194
+		switch d := d.(type) {
195
+		case *[]interface{}:
196
+			*d = s
197
+		case *interface{}:
198
+			*d = s
199
+		case nil:
200
+			// skip value
201
+		default:
202
+			if d := reflect.ValueOf(d); d.Type().Kind() != reflect.Ptr {
203
+				err = cannotConvert(d, s)
204
+			} else {
205
+				err = convertAssignArray(d.Elem(), s)
206
+			}
207
+		}
208
+	case Error:
209
+		err = s
210
+	default:
211
+		err = cannotConvert(reflect.ValueOf(d), s)
212
+	}
213
+	return
214
+}
215
+
216
+// Scan copies from src to the values pointed at by dest.
217
+//
218
+// The values pointed at by dest must be an integer, float, boolean, string,
219
+// []byte, interface{} or slices of these types. Scan uses the standard strconv
220
+// package to convert bulk strings to numeric and boolean types.
221
+//
222
+// If a dest value is nil, then the corresponding src value is skipped.
223
+//
224
+// If a src element is nil, then the corresponding dest value is not modified.
225
+//
226
+// To enable easy use of Scan in a loop, Scan returns the slice of src
227
+// following the copied values.
228
+func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
229
+	if len(src) < len(dest) {
230
+		return nil, errors.New("redigo.Scan: array short")
231
+	}
232
+	var err error
233
+	for i, d := range dest {
234
+		err = convertAssign(d, src[i])
235
+		if err != nil {
236
+			err = fmt.Errorf("redigo.Scan: cannot assign to dest %d: %v", i, err)
237
+			break
238
+		}
239
+	}
240
+	return src[len(dest):], err
241
+}
242
+
243
+type fieldSpec struct {
244
+	name      string
245
+	index     []int
246
+	omitEmpty bool
247
+}
248
+
249
+type structSpec struct {
250
+	m map[string]*fieldSpec
251
+	l []*fieldSpec
252
+}
253
+
254
+func (ss *structSpec) fieldSpec(name []byte) *fieldSpec {
255
+	return ss.m[string(name)]
256
+}
257
+
258
+func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *structSpec) {
259
+	for i := 0; i < t.NumField(); i++ {
260
+		f := t.Field(i)
261
+		switch {
262
+		case f.PkgPath != "" && !f.Anonymous:
263
+			// Ignore unexported fields.
264
+		case f.Anonymous:
265
+			// TODO: Handle pointers. Requires change to decoder and
266
+			// protection against infinite recursion.
267
+			if f.Type.Kind() == reflect.Struct {
268
+				compileStructSpec(f.Type, depth, append(index, i), ss)
269
+			}
270
+		default:
271
+			fs := &fieldSpec{name: f.Name}
272
+			tag := f.Tag.Get("redis")
273
+			p := strings.Split(tag, ",")
274
+			if len(p) > 0 {
275
+				if p[0] == "-" {
276
+					continue
277
+				}
278
+				if len(p[0]) > 0 {
279
+					fs.name = p[0]
280
+				}
281
+				for _, s := range p[1:] {
282
+					switch s {
283
+					case "omitempty":
284
+						fs.omitEmpty = true
285
+					default:
286
+						panic(fmt.Errorf("redigo: unknown field tag %s for type %s", s, t.Name()))
287
+					}
288
+				}
289
+			}
290
+			d, found := depth[fs.name]
291
+			if !found {
292
+				d = 1 << 30
293
+			}
294
+			switch {
295
+			case len(index) == d:
296
+				// At same depth, remove from result.
297
+				delete(ss.m, fs.name)
298
+				j := 0
299
+				for i := 0; i < len(ss.l); i++ {
300
+					if fs.name != ss.l[i].name {
301
+						ss.l[j] = ss.l[i]
302
+						j += 1
303
+					}
304
+				}
305
+				ss.l = ss.l[:j]
306
+			case len(index) < d:
307
+				fs.index = make([]int, len(index)+1)
308
+				copy(fs.index, index)
309
+				fs.index[len(index)] = i
310
+				depth[fs.name] = len(index)
311
+				ss.m[fs.name] = fs
312
+				ss.l = append(ss.l, fs)
313
+			}
314
+		}
315
+	}
316
+}
317
+
318
+var (
319
+	structSpecMutex  sync.RWMutex
320
+	structSpecCache  = make(map[reflect.Type]*structSpec)
321
+	defaultFieldSpec = &fieldSpec{}
322
+)
323
+
324
+func structSpecForType(t reflect.Type) *structSpec {
325
+
326
+	structSpecMutex.RLock()
327
+	ss, found := structSpecCache[t]
328
+	structSpecMutex.RUnlock()
329
+	if found {
330
+		return ss
331
+	}
332
+
333
+	structSpecMutex.Lock()
334
+	defer structSpecMutex.Unlock()
335
+	ss, found = structSpecCache[t]
336
+	if found {
337
+		return ss
338
+	}
339
+
340
+	ss = &structSpec{m: make(map[string]*fieldSpec)}
341
+	compileStructSpec(t, make(map[string]int), nil, ss)
342
+	structSpecCache[t] = ss
343
+	return ss
344
+}
345
+
346
+var errScanStructValue = errors.New("redigo.ScanStruct: value must be non-nil pointer to a struct")
347
+
348
+// ScanStruct scans alternating names and values from src to a struct. The
349
+// HGETALL and CONFIG GET commands return replies in this format.
350
+//
351
+// ScanStruct uses exported field names to match values in the response. Use
352
+// 'redis' field tag to override the name:
353
+//
354
+//      Field int `redis:"myName"`
355
+//
356
+// Fields with the tag redis:"-" are ignored.
357
+//
358
+// Integer, float, boolean, string and []byte fields are supported. Scan uses the
359
+// standard strconv package to convert bulk string values to numeric and
360
+// boolean types.
361
+//
362
+// If a src element is nil, then the corresponding field is not modified.
363
+func ScanStruct(src []interface{}, dest interface{}) error {
364
+	d := reflect.ValueOf(dest)
365
+	if d.Kind() != reflect.Ptr || d.IsNil() {
366
+		return errScanStructValue
367
+	}
368
+	d = d.Elem()
369
+	if d.Kind() != reflect.Struct {
370
+		return errScanStructValue
371
+	}
372
+	ss := structSpecForType(d.Type())
373
+
374
+	if len(src)%2 != 0 {
375
+		return errors.New("redigo.ScanStruct: number of values not a multiple of 2")
376
+	}
377
+
378
+	for i := 0; i < len(src); i += 2 {
379
+		s := src[i+1]
380
+		if s == nil {
381
+			continue
382
+		}
383
+		name, ok := src[i].([]byte)
384
+		if !ok {
385
+			return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value", i)
386
+		}
387
+		fs := ss.fieldSpec(name)
388
+		if fs == nil {
389
+			continue
390
+		}
391
+		if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
392
+			return fmt.Errorf("redigo.ScanStruct: cannot assign field %s: %v", fs.name, err)
393
+		}
394
+	}
395
+	return nil
396
+}
397
+
398
+var (
399
+	errScanSliceValue = errors.New("redigo.ScanSlice: dest must be non-nil pointer to a struct")
400
+)
401
+
402
+// ScanSlice scans src to the slice pointed to by dest. The elements the dest
403
+// slice must be integer, float, boolean, string, struct or pointer to struct
404
+// values.
405
+//
406
+// Struct fields must be integer, float, boolean or string values. All struct
407
+// fields are used unless a subset is specified using fieldNames.
408
+func ScanSlice(src []interface{}, dest interface{}, fieldNames ...string) error {
409
+	d := reflect.ValueOf(dest)
410
+	if d.Kind() != reflect.Ptr || d.IsNil() {
411
+		return errScanSliceValue
412
+	}
413
+	d = d.Elem()
414
+	if d.Kind() != reflect.Slice {
415
+		return errScanSliceValue
416
+	}
417
+
418
+	isPtr := false
419
+	t := d.Type().Elem()
420
+	if t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct {
421
+		isPtr = true
422
+		t = t.Elem()
423
+	}
424
+
425
+	if t.Kind() != reflect.Struct {
426
+		ensureLen(d, len(src))
427
+		for i, s := range src {
428
+			if s == nil {
429
+				continue
430
+			}
431
+			if err := convertAssignValue(d.Index(i), s); err != nil {
432
+				return fmt.Errorf("redigo.ScanSlice: cannot assign element %d: %v", i, err)
433
+			}
434
+		}
435
+		return nil
436
+	}
437
+
438
+	ss := structSpecForType(t)
439
+	fss := ss.l
440
+	if len(fieldNames) > 0 {
441
+		fss = make([]*fieldSpec, len(fieldNames))
442
+		for i, name := range fieldNames {
443
+			fss[i] = ss.m[name]
444
+			if fss[i] == nil {
445
+				return fmt.Errorf("redigo.ScanSlice: ScanSlice bad field name %s", name)
446
+			}
447
+		}
448
+	}
449
+
450
+	if len(fss) == 0 {
451
+		return errors.New("redigo.ScanSlice: no struct fields")
452
+	}
453
+
454
+	n := len(src) / len(fss)
455
+	if n*len(fss) != len(src) {
456
+		return errors.New("redigo.ScanSlice: length not a multiple of struct field count")
457
+	}
458
+
459
+	ensureLen(d, n)
460
+	for i := 0; i < n; i++ {
461
+		d := d.Index(i)
462
+		if isPtr {
463
+			if d.IsNil() {
464
+				d.Set(reflect.New(t))
465
+			}
466
+			d = d.Elem()
467
+		}
468
+		for j, fs := range fss {
469
+			s := src[i*len(fss)+j]
470
+			if s == nil {
471
+				continue
472
+			}
473
+			if err := convertAssignValue(d.FieldByIndex(fs.index), s); err != nil {
474
+				return fmt.Errorf("redigo.ScanSlice: cannot assign element %d to field %s: %v", i*len(fss)+j, fs.name, err)
475
+			}
476
+		}
477
+	}
478
+	return nil
479
+}
480
+
481
+// Args is a helper for constructing command arguments from structured values.
482
+type Args []interface{}
483
+
484
+// Add returns the result of appending value to args.
485
+func (args Args) Add(value ...interface{}) Args {
486
+	return append(args, value...)
487
+}
488
+
489
+// AddFlat returns the result of appending the flattened value of v to args.
490
+//
491
+// Maps are flattened by appending the alternating keys and map values to args.
492
+//
493
+// Slices are flattened by appending the slice elements to args.
494
+//
495
+// Structs are flattened by appending the alternating names and values of
496
+// exported fields to args. If v is a nil struct pointer, then nothing is
497
+// appended. The 'redis' field tag overrides struct field names. See ScanStruct
498
+// for more information on the use of the 'redis' field tag.
499
+//
500
+// Other types are appended to args as is.
501
+func (args Args) AddFlat(v interface{}) Args {
502
+	rv := reflect.ValueOf(v)
503
+	switch rv.Kind() {
504
+	case reflect.Struct:
505
+		args = flattenStruct(args, rv)
506
+	case reflect.Slice:
507
+		for i := 0; i < rv.Len(); i++ {
508
+			args = append(args, rv.Index(i).Interface())
509
+		}
510
+	case reflect.Map:
511
+		for _, k := range rv.MapKeys() {
512
+			args = append(args, k.Interface(), rv.MapIndex(k).Interface())
513
+		}
514
+	case reflect.Ptr:
515
+		if rv.Type().Elem().Kind() == reflect.Struct {
516
+			if !rv.IsNil() {
517
+				args = flattenStruct(args, rv.Elem())
518
+			}
519
+		} else {
520
+			args = append(args, v)
521
+		}
522
+	default:
523
+		args = append(args, v)
524
+	}
525
+	return args
526
+}
527
+
528
+func flattenStruct(args Args, v reflect.Value) Args {
529
+	ss := structSpecForType(v.Type())
530
+	for _, fs := range ss.l {
531
+		fv := v.FieldByIndex(fs.index)
532
+		if fs.omitEmpty {
533
+			var empty = false
534
+			switch fv.Kind() {
535
+			case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
536
+				empty = fv.Len() == 0
537
+			case reflect.Bool:
538
+				empty = !fv.Bool()
539
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
540
+				empty = fv.Int() == 0
541
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
542
+				empty = fv.Uint() == 0
543
+			case reflect.Float32, reflect.Float64:
544
+				empty = fv.Float() == 0
545
+			case reflect.Interface, reflect.Ptr:
546
+				empty = fv.IsNil()
547
+			}
548
+			if empty {
549
+				continue
550
+			}
551
+		}
552
+		args = append(args, fs.name, fv.Interface())
553
+	}
554
+	return args
555
+}

+ 86
- 0
vendor/github.com/garyburd/redigo/redis/script.go Bestand weergeven

@@ -0,0 +1,86 @@
1
+// Copyright 2012 Gary Burd
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
4
+// not use this file except in compliance with the License. You may obtain
5
+// a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+// License for the specific language governing permissions and limitations
13
+// under the License.
14
+
15
+package redis
16
+
17
+import (
18
+	"crypto/sha1"
19
+	"encoding/hex"
20
+	"io"
21
+	"strings"
22
+)
23
+
24
+// Script encapsulates the source, hash and key count for a Lua script. See
25
+// http://redis.io/commands/eval for information on scripts in Redis.
26
+type Script struct {
27
+	keyCount int
28
+	src      string
29
+	hash     string
30
+}
31
+
32
+// NewScript returns a new script object. If keyCount is greater than or equal
33
+// to zero, then the count is automatically inserted in the EVAL command
34
+// argument list. If keyCount is less than zero, then the application supplies
35
+// the count as the first value in the keysAndArgs argument to the Do, Send and
36
+// SendHash methods.
37
+func NewScript(keyCount int, src string) *Script {
38
+	h := sha1.New()
39
+	io.WriteString(h, src)
40
+	return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))}
41
+}
42
+
43
+func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} {
44
+	var args []interface{}
45
+	if s.keyCount < 0 {
46
+		args = make([]interface{}, 1+len(keysAndArgs))
47
+		args[0] = spec
48
+		copy(args[1:], keysAndArgs)
49
+	} else {
50
+		args = make([]interface{}, 2+len(keysAndArgs))
51
+		args[0] = spec
52
+		args[1] = s.keyCount
53
+		copy(args[2:], keysAndArgs)
54
+	}
55
+	return args
56
+}
57
+
58
+// Do evaluates the script. Under the covers, Do optimistically evaluates the
59
+// script using the EVALSHA command. If the command fails because the script is
60
+// not loaded, then Do evaluates the script using the EVAL command (thus
61
+// causing the script to load).
62
+func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) {
63
+	v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...)
64
+	if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") {
65
+		v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...)
66
+	}
67
+	return v, err
68
+}
69
+
70
+// SendHash evaluates the script without waiting for the reply. The script is
71
+// evaluated with the EVALSHA command. The application must ensure that the
72
+// script is loaded by a previous call to Send, Do or Load methods.
73
+func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error {
74
+	return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...)
75
+}
76
+
77
+// Send evaluates the script without waiting for the reply.
78
+func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error {
79
+	return c.Send("EVAL", s.args(s.src, keysAndArgs)...)
80
+}
81
+
82
+// Load loads the script without evaluating it.
83
+func (s *Script) Load(c Conn) error {
84
+	_, err := c.Do("SCRIPT", "LOAD", s.src)
85
+	return err
86
+}

+ 6372
- 0
vendor/github.com/osrg/gobgp/packet/bgp.go
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 28
- 0
vendor/github.com/osrg/gobgp/packet/bgpattrtype_string.go Bestand weergeven

@@ -0,0 +1,28 @@
1
+// generated by stringer -type BGPAttrType bgp.go; DO NOT EDIT
2
+
3
+package bgp
4
+
5
+import "fmt"
6
+
7
+const (
8
+	_BGPAttrType_name_0 = "BGP_ATTR_TYPE_ORIGINBGP_ATTR_TYPE_AS_PATHBGP_ATTR_TYPE_NEXT_HOPBGP_ATTR_TYPE_MULTI_EXIT_DISCBGP_ATTR_TYPE_LOCAL_PREFBGP_ATTR_TYPE_ATOMIC_AGGREGATEBGP_ATTR_TYPE_AGGREGATORBGP_ATTR_TYPE_COMMUNITIESBGP_ATTR_TYPE_ORIGINATOR_IDBGP_ATTR_TYPE_CLUSTER_LIST"
9
+	_BGPAttrType_name_1 = "BGP_ATTR_TYPE_MP_REACH_NLRIBGP_ATTR_TYPE_MP_UNREACH_NLRIBGP_ATTR_TYPE_EXTENDED_COMMUNITIESBGP_ATTR_TYPE_AS4_PATHBGP_ATTR_TYPE_AS4_AGGREGATOR"
10
+)
11
+
12
+var (
13
+	_BGPAttrType_index_0 = [...]uint8{0, 20, 41, 63, 92, 116, 146, 170, 195, 222, 248}
14
+	_BGPAttrType_index_1 = [...]uint8{0, 27, 56, 90, 112, 140}
15
+)
16
+
17
+func (i BGPAttrType) String() string {
18
+	switch {
19
+	case 1 <= i && i <= 10:
20
+		i -= 1
21
+		return _BGPAttrType_name_0[_BGPAttrType_index_0[i]:_BGPAttrType_index_0[i+1]]
22
+	case 14 <= i && i <= 18:
23
+		i -= 14
24
+		return _BGPAttrType_name_1[_BGPAttrType_index_1[i]:_BGPAttrType_index_1[i+1]]
25
+	default:
26
+		return fmt.Sprintf("BGPAttrType(%d)", i)
27
+	}
28
+}

+ 40
- 0
vendor/github.com/osrg/gobgp/packet/bgpcapabilitycode_string.go Bestand weergeven

@@ -0,0 +1,40 @@
1
+// generated by stringer -type=BGPCapabilityCode; DO NOT EDIT
2
+
3
+package bgp
4
+
5
+import "fmt"
6
+
7
+const (
8
+	_BGPCapabilityCode_name_0 = "BGP_CAP_MULTIPROTOCOLBGP_CAP_ROUTE_REFRESH"
9
+	_BGPCapabilityCode_name_1 = "BGP_CAP_CARRYING_LABEL_INFO"
10
+	_BGPCapabilityCode_name_2 = "BGP_CAP_GRACEFUL_RESTARTBGP_CAP_FOUR_OCTET_AS_NUMBER"
11
+	_BGPCapabilityCode_name_3 = "BGP_CAP_ENHANCED_ROUTE_REFRESH"
12
+	_BGPCapabilityCode_name_4 = "BGP_CAP_ROUTE_REFRESH_CISCO"
13
+)
14
+
15
+var (
16
+	_BGPCapabilityCode_index_0 = [...]uint8{0, 21, 42}
17
+	_BGPCapabilityCode_index_1 = [...]uint8{0, 27}
18
+	_BGPCapabilityCode_index_2 = [...]uint8{0, 24, 52}
19
+	_BGPCapabilityCode_index_3 = [...]uint8{0, 30}
20
+	_BGPCapabilityCode_index_4 = [...]uint8{0, 27}
21
+)
22
+
23
+func (i BGPCapabilityCode) String() string {
24
+	switch {
25
+	case 1 <= i && i <= 2:
26
+		i -= 1
27
+		return _BGPCapabilityCode_name_0[_BGPCapabilityCode_index_0[i]:_BGPCapabilityCode_index_0[i+1]]
28
+	case i == 4:
29
+		return _BGPCapabilityCode_name_1
30
+	case 64 <= i && i <= 65:
31
+		i -= 64
32
+		return _BGPCapabilityCode_name_2[_BGPCapabilityCode_index_2[i]:_BGPCapabilityCode_index_2[i+1]]
33
+	case i == 70:
34
+		return _BGPCapabilityCode_name_3
35
+	case i == 128:
36
+		return _BGPCapabilityCode_name_4
37
+	default:
38
+		return fmt.Sprintf("BGPCapabilityCode(%d)", i)
39
+	}
40
+}

+ 609
- 0
vendor/github.com/osrg/gobgp/packet/bmp.go Bestand weergeven

@@ -0,0 +1,609 @@
1
+// Copyright (C) 2014,2015 Nippon Telegraph and Telephone Corporation.
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+//    http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
+// implied.
13
+// See the License for the specific language governing permissions and
14
+// limitations under the License.
15
+
16
+package bgp
17
+
18
+import (
19
+	"encoding/binary"
20
+	"fmt"
21
+	"math"
22
+	"net"
23
+)
24
+
25
+type BMPHeader struct {
26
+	Version uint8
27
+	Length  uint32
28
+	Type    uint8
29
+}
30
+
31
+const (
32
+	BMP_VERSION          = 3
33
+	BMP_HEADER_SIZE      = 6
34
+	BMP_PEER_HEADER_SIZE = 42
35
+)
36
+
37
+const (
38
+	BMP_DEFAULT_PORT = 11019
39
+)
40
+
41
+const (
42
+	BMP_PEER_TYPE_GLOBAL uint8 = iota
43
+	BMP_PEER_TYPE_L3VPN
44
+)
45
+
46
+func (h *BMPHeader) DecodeFromBytes(data []byte) error {
47
+	h.Version = data[0]
48
+	if data[0] != BMP_VERSION {
49
+		return fmt.Errorf("error version")
50
+	}
51
+	h.Length = binary.BigEndian.Uint32(data[1:5])
52
+	h.Type = data[5]
53
+	return nil
54
+}
55
+
56
+func (h *BMPHeader) Serialize() ([]byte, error) {
57
+	buf := make([]byte, BMP_HEADER_SIZE)
58
+	buf[0] = h.Version
59
+	binary.BigEndian.PutUint32(buf[1:], h.Length)
60
+	buf[5] = h.Type
61
+	return buf, nil
62
+}
63
+
64
+type BMPPeerHeader struct {
65
+	PeerType          uint8
66
+	IsPostPolicy      bool
67
+	PeerDistinguisher uint64
68
+	PeerAddress       net.IP
69
+	PeerAS            uint32
70
+	PeerBGPID         net.IP
71
+	Timestamp         float64
72
+	Flags             uint8
73
+}
74
+
75
+func NewBMPPeerHeader(t uint8, policy bool, dist uint64, address string, as uint32, id string, stamp float64) *BMPPeerHeader {
76
+	h := &BMPPeerHeader{
77
+		PeerType:          t,
78
+		IsPostPolicy:      policy,
79
+		PeerDistinguisher: dist,
80
+		PeerAS:            as,
81
+		PeerBGPID:         net.ParseIP(id).To4(),
82
+		Timestamp:         stamp,
83
+	}
84
+	if policy == true {
85
+		h.Flags |= (1 << 6)
86
+	}
87
+	if net.ParseIP(address).To4() != nil {
88
+		h.PeerAddress = net.ParseIP(address).To4()
89
+	} else {
90
+		h.PeerAddress = net.ParseIP(address).To16()
91
+		h.Flags |= (1 << 7)
92
+	}
93
+	return h
94
+}
95
+
96
+func (h *BMPPeerHeader) DecodeFromBytes(data []byte) error {
97
+	h.PeerType = data[0]
98
+	h.Flags = data[1]
99
+	if h.Flags&(1<<6) != 0 {
100
+		h.IsPostPolicy = true
101
+	} else {
102
+		h.IsPostPolicy = false
103
+	}
104
+	h.PeerDistinguisher = binary.BigEndian.Uint64(data[2:10])
105
+	if h.Flags&(1<<7) != 0 {
106
+		h.PeerAddress = net.IP(data[10:26]).To16()
107
+	} else {
108
+		h.PeerAddress = net.IP(data[10:14]).To4()
109
+	}
110
+	h.PeerAS = binary.BigEndian.Uint32(data[26:30])
111
+	h.PeerBGPID = data[30:34]
112
+
113
+	timestamp1 := binary.BigEndian.Uint32(data[34:38])
114
+	timestamp2 := binary.BigEndian.Uint32(data[38:42])
115
+	h.Timestamp = float64(timestamp1) + float64(timestamp2)*math.Pow10(-6)
116
+	return nil
117
+}
118
+
119
+func (h *BMPPeerHeader) Serialize() ([]byte, error) {
120
+	buf := make([]byte, BMP_PEER_HEADER_SIZE)
121
+	buf[0] = h.PeerType
122
+	buf[1] = h.Flags
123
+	binary.BigEndian.PutUint64(buf[2:10], h.PeerDistinguisher)
124
+	if h.Flags&(1<<7) != 0 {
125
+		copy(buf[10:26], h.PeerAddress)
126
+	} else {
127
+		copy(buf[10:14], h.PeerAddress.To4())
128
+	}
129
+	binary.BigEndian.PutUint32(buf[26:30], h.PeerAS)
130
+	copy(buf[30:34], h.PeerBGPID)
131
+	t1, t2 := math.Modf(h.Timestamp)
132
+	t2 = math.Ceil(t2 * math.Pow10(6))
133
+	binary.BigEndian.PutUint32(buf[34:38], uint32(t1))
134
+	binary.BigEndian.PutUint32(buf[38:42], uint32(t2))
135
+	return buf, nil
136
+}
137
+
138
+type BMPRouteMonitoring struct {
139
+	BGPUpdate        *BGPMessage
140
+	BGPUpdatePayload []byte
141
+}
142
+
143
+func NewBMPRouteMonitoring(p BMPPeerHeader, update *BGPMessage) *BMPMessage {
144
+	return &BMPMessage{
145
+		Header: BMPHeader{
146
+			Version: BMP_VERSION,
147
+			Type:    BMP_MSG_ROUTE_MONITORING,
148
+		},
149
+		PeerHeader: p,
150
+		Body: &BMPRouteMonitoring{
151
+			BGPUpdate: update,
152
+		},
153
+	}
154
+}
155
+
156
+func (body *BMPRouteMonitoring) ParseBody(msg *BMPMessage, data []byte) error {
157
+	update, err := ParseBGPMessage(data)
158
+	if err != nil {
159
+		return err
160
+	}
161
+	body.BGPUpdate = update
162
+	return nil
163
+}
164
+
165
+func (body *BMPRouteMonitoring) Serialize() ([]byte, error) {
166
+	if body.BGPUpdatePayload != nil {
167
+		return body.BGPUpdatePayload, nil
168
+	}
169
+	return body.BGPUpdate.Serialize()
170
+}
171
+
172
+const (
173
+	BMP_STAT_TYPE_REJECTED = iota
174
+	BMP_STAT_TYPE_DUPLICATE_PREFIX
175
+	BMP_STAT_TYPE_DUPLICATE_WITHDRAW
176
+	BMP_STAT_TYPE_INV_UPDATE_DUE_TO_CLUSTER_LIST_LOOP
177
+	BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_PATH_LOOP
178
+	BMP_STAT_TYPE_INV_UPDATE_DUE_TO_ORIGINATOR_ID
179
+	BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP
180
+	BMP_STAT_TYPE_ADJ_RIB_IN
181
+	BMP_STAT_TYPE_LOC_RIB
182
+)
183
+
184
+type BMPStatsTLV struct {
185
+	Type   uint16
186
+	Length uint16
187
+	Value  uint64
188
+}
189
+
190
+type BMPStatisticsReport struct {
191
+	Count uint32
192
+	Stats []BMPStatsTLV
193
+}
194
+
195
+const (
196
+	BMP_PEER_DOWN_REASON_UNKNOWN = iota
197
+	BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION
198
+	BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION
199
+	BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION
200
+	BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION
201
+)
202
+
203
+type BMPPeerDownNotification struct {
204
+	Reason          uint8
205
+	BGPNotification *BGPMessage
206
+	Data            []byte
207
+}
208
+
209
+func NewBMPPeerDownNotification(p BMPPeerHeader, reason uint8, notification *BGPMessage, data []byte) *BMPMessage {
210
+	b := &BMPPeerDownNotification{
211
+		Reason: reason,
212
+	}
213
+	switch reason {
214
+	case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
215
+		b.BGPNotification = notification
216
+	default:
217
+		b.Data = data
218
+	}
219
+	return &BMPMessage{
220
+		Header: BMPHeader{
221
+			Version: BMP_VERSION,
222
+			Type:    BMP_MSG_PEER_DOWN_NOTIFICATION,
223
+		},
224
+		PeerHeader: p,
225
+		Body:       b,
226
+	}
227
+}
228
+
229
+func (body *BMPPeerDownNotification) ParseBody(msg *BMPMessage, data []byte) error {
230
+	body.Reason = data[0]
231
+	data = data[1:]
232
+	if body.Reason == BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION || body.Reason == BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION {
233
+		notification, err := ParseBGPMessage(data)
234
+		if err != nil {
235
+			return err
236
+		}
237
+		body.BGPNotification = notification
238
+	} else {
239
+		body.Data = data
240
+	}
241
+	return nil
242
+}
243
+
244
+func (body *BMPPeerDownNotification) Serialize() ([]byte, error) {
245
+	buf := make([]byte, 1)
246
+	buf[0] = body.Reason
247
+	switch body.Reason {
248
+	case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION:
249
+		if body.BGPNotification != nil {
250
+			b, err := body.BGPNotification.Serialize()
251
+			if err != nil {
252
+				return nil, err
253
+			} else {
254
+				buf = append(buf, b...)
255
+			}
256
+		}
257
+	default:
258
+		if body.Data != nil {
259
+			buf = append(buf, body.Data...)
260
+		}
261
+	}
262
+	return buf, nil
263
+}
264
+
265
+type BMPPeerUpNotification struct {
266
+	LocalAddress    net.IP
267
+	LocalPort       uint16
268
+	RemotePort      uint16
269
+	SentOpenMsg     *BGPMessage
270
+	ReceivedOpenMsg *BGPMessage
271
+}
272
+
273
+func NewBMPPeerUpNotification(p BMPPeerHeader, lAddr string, lPort, rPort uint16, sent, recv *BGPMessage) *BMPMessage {
274
+	b := &BMPPeerUpNotification{
275
+		LocalPort:       lPort,
276
+		RemotePort:      rPort,
277
+		SentOpenMsg:     sent,
278
+		ReceivedOpenMsg: recv,
279
+	}
280
+	addr := net.ParseIP(lAddr)
281
+	if addr.To4() != nil {
282
+		b.LocalAddress = addr.To4()
283
+	} else {
284
+		b.LocalAddress = addr.To16()
285
+	}
286
+	return &BMPMessage{
287
+		Header: BMPHeader{
288
+			Version: BMP_VERSION,
289
+			Type:    BMP_MSG_PEER_UP_NOTIFICATION,
290
+		},
291
+		PeerHeader: p,
292
+		Body:       b,
293
+	}
294
+}
295
+
296
+func (body *BMPPeerUpNotification) ParseBody(msg *BMPMessage, data []byte) error {
297
+	if msg.PeerHeader.Flags&(1<<7) != 0 {
298
+		body.LocalAddress = net.IP(data[:16]).To16()
299
+	} else {
300
+		body.LocalAddress = net.IP(data[:4]).To4()
301
+	}
302
+
303
+	body.LocalPort = binary.BigEndian.Uint16(data[16:18])
304
+	body.RemotePort = binary.BigEndian.Uint16(data[18:20])
305
+
306
+	data = data[20:]
307
+	sentopen, err := ParseBGPMessage(data)
308
+	if err != nil {
309
+		return err
310
+	}
311
+	body.SentOpenMsg = sentopen
312
+	data = data[body.SentOpenMsg.Header.Len:]
313
+	body.ReceivedOpenMsg, err = ParseBGPMessage(data)
314
+	if err != nil {
315
+		return err
316
+	}
317
+	return nil
318
+}
319
+
320
+func (body *BMPPeerUpNotification) Serialize() ([]byte, error) {
321
+	buf := make([]byte, 20)
322
+	if body.LocalAddress.To4() != nil {
323
+		copy(buf[:4], body.LocalAddress.To4())
324
+	} else {
325
+		copy(buf[:16], body.LocalAddress.To16())
326
+	}
327
+
328
+	binary.BigEndian.PutUint16(buf[16:18], body.LocalPort)
329
+	binary.BigEndian.PutUint16(buf[18:20], body.RemotePort)
330
+
331
+	m, _ := body.SentOpenMsg.Serialize()
332
+	buf = append(buf, m...)
333
+	m, _ = body.ReceivedOpenMsg.Serialize()
334
+	buf = append(buf, m...)
335
+	return buf, nil
336
+}
337
+
338
+func (body *BMPStatisticsReport) ParseBody(msg *BMPMessage, data []byte) error {
339
+	body.Count = binary.BigEndian.Uint32(data[0:4])
340
+	data = data[4:]
341
+	for len(data) >= 4 {
342
+		s := BMPStatsTLV{}
343
+		s.Type = binary.BigEndian.Uint16(data[0:2])
344
+		s.Length = binary.BigEndian.Uint16(data[2:4])
345
+		data = data[4:]
346
+		if len(data) < int(s.Length) {
347
+			break
348
+		}
349
+		if s.Type == BMP_STAT_TYPE_ADJ_RIB_IN || s.Type == BMP_STAT_TYPE_LOC_RIB {
350
+			if s.Length < 8 {
351
+				break
352
+			}
353
+			s.Value = binary.BigEndian.Uint64(data[:8])
354
+		} else {
355
+			if s.Length < 4 {
356
+				break
357
+			}
358
+			s.Value = uint64(binary.BigEndian.Uint32(data[:4]))
359
+		}
360
+		body.Stats = append(body.Stats, s)
361
+		data = data[s.Length:]
362
+	}
363
+	return nil
364
+}
365
+
366
+func (body *BMPStatisticsReport) Serialize() ([]byte, error) {
367
+	// TODO
368
+	buf := make([]byte, 4)
369
+	body.Count = uint32(len(body.Stats))
370
+	binary.BigEndian.PutUint32(buf[0:4], body.Count)
371
+
372
+	return buf, nil
373
+}
374
+
375
+type BMPTLV struct {
376
+	Type   uint16
377
+	Length uint16
378
+	Value  []byte
379
+}
380
+
381
+func NewBMPTLV(t uint16, v []byte) *BMPTLV {
382
+	return &BMPTLV{
383
+		Type:   t,
384
+		Length: uint16(len(v)),
385
+		Value:  v,
386
+	}
387
+}
388
+
389
+func (tlv *BMPTLV) DecodeFromBytes(data []byte) error {
390
+	//TODO: check data length
391
+	tlv.Type = binary.BigEndian.Uint16(data[0:2])
392
+	tlv.Length = binary.BigEndian.Uint16(data[2:4])
393
+	tlv.Value = data[4 : 4+tlv.Length]
394
+	return nil
395
+}
396
+
397
+func (tlv *BMPTLV) Serialize() ([]byte, error) {
398
+	if tlv.Length == 0 {
399
+		tlv.Length = uint16(len(tlv.Value))
400
+	}
401
+	buf := make([]byte, 4+tlv.Length)
402
+	binary.BigEndian.PutUint16(buf[0:2], tlv.Type)
403
+	binary.BigEndian.PutUint16(buf[2:4], tlv.Length)
404
+	copy(buf[4:], tlv.Value)
405
+	return buf, nil
406
+}
407
+
408
+func (tlv *BMPTLV) Len() int {
409
+	return 4 + int(tlv.Length)
410
+}
411
+
412
+type BMPInitiation struct {
413
+	Info []BMPTLV
414
+}
415
+
416
+func NewBMPInitiation(info []BMPTLV) *BMPMessage {
417
+	return &BMPMessage{
418
+		Header: BMPHeader{
419
+			Version: BMP_VERSION,
420
+			Type:    BMP_MSG_INITIATION,
421
+		},
422
+		Body: &BMPInitiation{
423
+			Info: info,
424
+		},
425
+	}
426
+}
427
+
428
+func (body *BMPInitiation) ParseBody(msg *BMPMessage, data []byte) error {
429
+	for len(data) > 0 {
430
+		tlv := BMPTLV{}
431
+		tlv.DecodeFromBytes(data)
432
+		body.Info = append(body.Info, tlv)
433
+		data = data[tlv.Len():]
434
+	}
435
+	return nil
436
+}
437
+
438
+func (body *BMPInitiation) Serialize() ([]byte, error) {
439
+	buf := make([]byte, 0)
440
+	for _, tlv := range body.Info {
441
+		b, err := tlv.Serialize()
442
+		if err != nil {
443
+			return buf, err
444
+		}
445
+		buf = append(buf, b...)
446
+	}
447
+	return buf, nil
448
+}
449
+
450
+type BMPTermination struct {
451
+	Info []BMPTLV
452
+}
453
+
454
+func NewBMPTermination(info []BMPTLV) *BMPMessage {
455
+	return &BMPMessage{
456
+		Header: BMPHeader{
457
+			Version: BMP_VERSION,
458
+			Type:    BMP_MSG_TERMINATION,
459
+		},
460
+		Body: &BMPTermination{
461
+			Info: info,
462
+		},
463
+	}
464
+}
465
+
466
+func (body *BMPTermination) ParseBody(msg *BMPMessage, data []byte) error {
467
+	for len(data) > 0 {
468
+		tlv := BMPTLV{}
469
+		tlv.DecodeFromBytes(data)
470
+		body.Info = append(body.Info, tlv)
471
+		data = data[tlv.Len():]
472
+	}
473
+	return nil
474
+}
475
+
476
+func (body *BMPTermination) Serialize() ([]byte, error) {
477
+	buf := make([]byte, 0)
478
+	for _, tlv := range body.Info {
479
+		b, err := tlv.Serialize()
480
+		if err != nil {
481
+			return buf, err
482
+		}
483
+		buf = append(buf, b...)
484
+	}
485
+	return buf, nil
486
+}
487
+
488
+type BMPBody interface {
489
+	// Sigh, some body messages need a BMPHeader to parse the body
490
+	// data so we need to pass BMPHeader (avoid DecodeFromBytes
491
+	// function name).
492
+	ParseBody(*BMPMessage, []byte) error
493
+	Serialize() ([]byte, error)
494
+}
495
+
496
+type BMPMessage struct {
497
+	Header     BMPHeader
498
+	PeerHeader BMPPeerHeader
499
+	Body       BMPBody
500
+}
501
+
502
+func (msg *BMPMessage) Serialize() ([]byte, error) {
503
+	buf := make([]byte, 0)
504
+	if msg.Header.Type != BMP_MSG_INITIATION {
505
+		p, err := msg.PeerHeader.Serialize()
506
+		if err != nil {
507
+			return nil, err
508
+		}
509
+		buf = append(buf, p...)
510
+	}
511
+
512
+	b, err := msg.Body.Serialize()
513
+	if err != nil {
514
+		return nil, err
515
+	}
516
+	buf = append(buf, b...)
517
+
518
+	if msg.Header.Length == 0 {
519
+		msg.Header.Length = uint32(BMP_HEADER_SIZE + len(buf))
520
+	}
521
+
522
+	h, err := msg.Header.Serialize()
523
+	if err != nil {
524
+		return nil, err
525
+	}
526
+	return append(h, buf...), nil
527
+}
528
+
529
+func (msg *BMPMessage) Len() int {
530
+	return int(msg.Header.Length)
531
+}
532
+
533
+const (
534
+	BMP_MSG_ROUTE_MONITORING = iota
535
+	BMP_MSG_STATISTICS_REPORT
536
+	BMP_MSG_PEER_DOWN_NOTIFICATION
537
+	BMP_MSG_PEER_UP_NOTIFICATION
538
+	BMP_MSG_INITIATION
539
+	BMP_MSG_TERMINATION
540
+)
541
+
542
+func ParseBMPMessage(data []byte) (*BMPMessage, error) {
543
+	msg := &BMPMessage{}
544
+	err := msg.Header.DecodeFromBytes(data)
545
+	if err != nil {
546
+		return nil, err
547
+	}
548
+	data = data[BMP_HEADER_SIZE:msg.Header.Length]
549
+
550
+	switch msg.Header.Type {
551
+	case BMP_MSG_ROUTE_MONITORING:
552
+		msg.Body = &BMPRouteMonitoring{}
553
+	case BMP_MSG_STATISTICS_REPORT:
554
+		msg.Body = &BMPStatisticsReport{}
555
+	case BMP_MSG_PEER_DOWN_NOTIFICATION:
556
+		msg.Body = &BMPPeerDownNotification{}
557
+	case BMP_MSG_PEER_UP_NOTIFICATION:
558
+		msg.Body = &BMPPeerUpNotification{}
559
+	case BMP_MSG_INITIATION:
560
+		msg.Body = &BMPInitiation{}
561
+	case BMP_MSG_TERMINATION:
562
+		msg.Body = &BMPTermination{}
563
+	}
564
+
565
+	if msg.Header.Type != BMP_MSG_INITIATION {
566
+		msg.PeerHeader.DecodeFromBytes(data)
567
+		data = data[BMP_PEER_HEADER_SIZE:]
568
+	}
569
+
570
+	err = msg.Body.ParseBody(msg, data)
571
+	if err != nil {
572
+		return nil, err
573
+	}
574
+	return msg, nil
575
+}
576
+
577
+type MessageError struct {
578
+	TypeCode    uint8
579
+	SubTypeCode uint8
580
+	Data        []byte
581
+	Message     string
582
+}
583
+
584
+func NewMessageError(typeCode, subTypeCode uint8, data []byte, msg string) error {
585
+	return &MessageError{
586
+		TypeCode:    typeCode,
587
+		SubTypeCode: subTypeCode,
588
+		Data:        data,
589
+		Message:     msg,
590
+	}
591
+}
592
+
593
+func (e *MessageError) Error() string {
594
+	return e.Message
595
+}
596
+
597
+func SplitBMP(data []byte, atEOF bool) (advance int, token []byte, err error) {
598
+	if atEOF && len(data) == 0 || len(data) < BMP_HEADER_SIZE {
599
+		return 0, nil, nil
600
+	}
601
+
602
+	msg := &BMPMessage{}
603
+	msg.Header.DecodeFromBytes(data)
604
+	if uint32(len(data)) < msg.Header.Length {
605
+		return 0, nil, nil
606
+	}
607
+
608
+	return int(msg.Header.Length), data[0:msg.Header.Length], nil
609
+}

+ 133
- 0
vendor/github.com/osrg/gobgp/packet/constant.go Bestand weergeven

@@ -0,0 +1,133 @@
1
+// Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+//    http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
+// implied.
13
+// See the License for the specific language governing permissions and
14
+// limitations under the License.
15
+
16
+package bgp
17
+
18
+import (
19
+	"fmt"
20
+	"strings"
21
+)
22
+
23
+const AS_TRANS = 23456
24
+
25
+const BGP_PORT = 179
26
+
27
+type FSMState int
28
+
29
+const (
30
+	BGP_FSM_IDLE FSMState = iota
31
+	BGP_FSM_CONNECT
32
+	BGP_FSM_ACTIVE
33
+	BGP_FSM_OPENSENT
34
+	BGP_FSM_OPENCONFIRM
35
+	BGP_FSM_ESTABLISHED
36
+)
37
+
38
+// partially taken from http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
39
+type Protocol int
40
+
41
+const (
42
+	Unknown Protocol = iota
43
+	ICMP             = 0x01
44
+	IGMP             = 0x02
45
+	TCP              = 0x06
46
+	EGP              = 0x08
47
+	IGP              = 0x09
48
+	UDP              = 0x11
49
+	RSVP             = 0x2e
50
+	GRE              = 0x2f
51
+	OSPF             = 0x59
52
+	IPIP             = 0x5e
53
+	PIM              = 0x67
54
+	SCTP             = 0x84
55
+)
56
+
57
+var ProtocolNameMap = map[Protocol]string{
58
+	Unknown: "unknown",
59
+	ICMP:    "icmp",
60
+	IGMP:    "igmp",
61
+	TCP:     "tcp",
62
+	EGP:     "egp",
63
+	IGP:     "igp",
64
+	UDP:     "udp",
65
+	RSVP:    "rsvp",
66
+	GRE:     "gre",
67
+	OSPF:    "ospf",
68
+	IPIP:    "ipip",
69
+	PIM:     "pim",
70
+	SCTP:    "sctp",
71
+}
72
+
73
+var ProtocolValueMap = map[string]Protocol{
74
+	ProtocolNameMap[ICMP]: ICMP,
75
+	ProtocolNameMap[IGMP]: IGMP,
76
+	ProtocolNameMap[TCP]:  TCP,
77
+	ProtocolNameMap[EGP]:  EGP,
78
+	ProtocolNameMap[IGP]:  IGP,
79
+	ProtocolNameMap[UDP]:  UDP,
80
+	ProtocolNameMap[RSVP]: RSVP,
81
+	ProtocolNameMap[GRE]:  GRE,
82
+	ProtocolNameMap[OSPF]: OSPF,
83
+	ProtocolNameMap[IPIP]: IPIP,
84
+	ProtocolNameMap[PIM]:  PIM,
85
+	ProtocolNameMap[SCTP]: SCTP,
86
+}
87
+
88
+func (p Protocol) String() string {
89
+	name, ok := ProtocolNameMap[p]
90
+	if !ok {
91
+		return fmt.Sprintf("%d", p)
92
+	}
93
+	return name
94
+}
95
+
96
+type TCPFlag int
97
+
98
+const (
99
+	TCP_FLAG_FIN    = 0x01
100
+	TCP_FLAG_SYN    = 0x02
101
+	TCP_FLAG_RST    = 0x04
102
+	TCP_FLAG_PUSH   = 0x08
103
+	TCP_FLAG_ACK    = 0x10
104
+	TCP_FLAG_URGENT = 0x20
105
+)
106
+
107
+var TCPFlagNameMap = map[TCPFlag]string{
108
+	TCP_FLAG_FIN:    "fin",
109
+	TCP_FLAG_SYN:    "syn",
110
+	TCP_FLAG_RST:    "rst",
111
+	TCP_FLAG_PUSH:   "push",
112
+	TCP_FLAG_ACK:    "ack",
113
+	TCP_FLAG_URGENT: "urgent",
114
+}
115
+
116
+var TCPFlagValueMap = map[string]TCPFlag{
117
+	TCPFlagNameMap[TCP_FLAG_FIN]:    TCP_FLAG_FIN,
118
+	TCPFlagNameMap[TCP_FLAG_SYN]:    TCP_FLAG_SYN,
119
+	TCPFlagNameMap[TCP_FLAG_RST]:    TCP_FLAG_RST,
120
+	TCPFlagNameMap[TCP_FLAG_PUSH]:   TCP_FLAG_PUSH,
121
+	TCPFlagNameMap[TCP_FLAG_ACK]:    TCP_FLAG_ACK,
122
+	TCPFlagNameMap[TCP_FLAG_URGENT]: TCP_FLAG_URGENT,
123
+}
124
+
125
+func (f TCPFlag) String() string {
126
+	ss := make([]string, 0, 6)
127
+	for _, v := range []TCPFlag{TCP_FLAG_FIN, TCP_FLAG_SYN, TCP_FLAG_RST, TCP_FLAG_PUSH, TCP_FLAG_ACK, TCP_FLAG_URGENT} {
128
+		if f&v > 0 {
129
+			ss = append(ss, TCPFlagNameMap[v])
130
+		}
131
+	}
132
+	return strings.Join(ss, "|")
133
+}

+ 16
- 0
vendor/github.com/osrg/gobgp/packet/esitype_string.go Bestand weergeven

@@ -0,0 +1,16 @@
1
+// generated by stringer -type=ESIType bgp.go validate.go; DO NOT EDIT
2
+
3
+package bgp
4
+
5
+import "fmt"
6
+
7
+const _ESIType_name = "ESI_ARBITRARYESI_LACPESI_MSTPESI_MACESI_ROUTERIDESI_AS"
8
+
9
+var _ESIType_index = [...]uint8{0, 13, 21, 29, 36, 48, 54}
10
+
11
+func (i ESIType) String() string {
12
+	if i+1 >= ESIType(len(_ESIType_index)) {
13
+		return fmt.Sprintf("ESIType(%d)", i)
14
+	}
15
+	return _ESIType_name[_ESIType_index[i]:_ESIType_index[i+1]]
16
+}

+ 16
- 0
vendor/github.com/osrg/gobgp/packet/fsmstate_string.go Bestand weergeven

@@ -0,0 +1,16 @@
1
+// generated by stringer -type=FSMState -output=fsmstate_string.go bgp.go validate.go mrt.go rtr.go constant.go bmp.go esitype_string.go bgpattrtype_string.go; DO NOT EDIT
2
+
3
+package bgp
4
+
5
+import "fmt"
6
+
7
+const _FSMState_name = "BGP_FSM_IDLEBGP_FSM_CONNECTBGP_FSM_ACTIVEBGP_FSM_OPENSENTBGP_FSM_OPENCONFIRMBGP_FSM_ESTABLISHED"
8
+
9
+var _FSMState_index = [...]uint8{0, 12, 27, 41, 57, 76, 95}
10
+
11
+func (i FSMState) String() string {
12
+	if i < 0 || i >= FSMState(len(_FSMState_index)-1) {
13
+		return fmt.Sprintf("FSMState(%d)", i)
14
+	}
15
+	return _FSMState_name[_FSMState_index[i]:_FSMState_index[i+1]]
16
+}

+ 798
- 0
vendor/github.com/osrg/gobgp/packet/mrt.go Bestand weergeven

@@ -0,0 +1,798 @@
1
+// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+//    http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
+// implied.
13
+// See the License for the specific language governing permissions and
14
+// limitations under the License.
15
+
16
+package bgp
17
+
18
+import (
19
+	"bytes"
20
+	"encoding/binary"
21
+	"fmt"
22
+	"math"
23
+	"net"
24
+	"time"
25
+)
26
+
27
+const (
28
+	MRT_COMMON_HEADER_LEN = 12
29
+)
30
+
31
+type MRTType uint16
32
+
33
+const (
34
+	NULL         MRTType = 0  // deprecated
35
+	START        MRTType = 1  // deprecated
36
+	DIE          MRTType = 2  // deprecated
37
+	I_AM_DEAD    MRTType = 3  // deprecated
38
+	PEER_DOWN    MRTType = 4  // deprecated
39
+	BGP          MRTType = 5  // deprecated
40
+	RIP          MRTType = 6  // deprecated
41
+	IDRP         MRTType = 7  // deprecated
42
+	RIPNG        MRTType = 8  // deprecated
43
+	BGP4PLUS     MRTType = 9  // deprecated
44
+	BGP4PLUS01   MRTType = 10 // deprecated
45
+	OSPFv2       MRTType = 11
46
+	TABLE_DUMP   MRTType = 12
47
+	TABLE_DUMPv2 MRTType = 13
48
+	BGP4MP       MRTType = 16
49
+	BGP4MP_ET    MRTType = 17
50
+	ISIS         MRTType = 32
51
+	ISIS_ET      MRTType = 33
52
+	OSPFv3       MRTType = 48
53
+	OSPFv3_ET    MRTType = 49
54
+)
55
+
56
+type MRTSubTyper interface {
57
+	ToUint16() uint16
58
+}
59
+
60
+type MRTSubTypeTableDumpv2 uint16
61
+
62
+const (
63
+	PEER_INDEX_TABLE   MRTSubTypeTableDumpv2 = 1
64
+	RIB_IPV4_UNICAST   MRTSubTypeTableDumpv2 = 2
65
+	RIB_IPV4_MULTICAST MRTSubTypeTableDumpv2 = 3
66
+	RIB_IPV6_UNICAST   MRTSubTypeTableDumpv2 = 4
67
+	RIB_IPV6_MULTICAST MRTSubTypeTableDumpv2 = 5
68
+	RIB_GENERIC        MRTSubTypeTableDumpv2 = 6
69
+)
70
+
71
+func (t MRTSubTypeTableDumpv2) ToUint16() uint16 {
72
+	return uint16(t)
73
+}
74
+
75
+type MRTSubTypeBGP4MP uint16
76
+
77
+const (
78
+	STATE_CHANGE      MRTSubTypeBGP4MP = 0
79
+	MESSAGE           MRTSubTypeBGP4MP = 1
80
+	MESSAGE_AS4       MRTSubTypeBGP4MP = 4
81
+	STATE_CHANGE_AS4  MRTSubTypeBGP4MP = 5
82
+	MESSAGE_LOCAL     MRTSubTypeBGP4MP = 6
83
+	MESSAGE_AS4_LOCAL MRTSubTypeBGP4MP = 7
84
+)
85
+
86
+func (t MRTSubTypeBGP4MP) ToUint16() uint16 {
87
+	return uint16(t)
88
+}
89
+
90
+type BGPState uint16
91
+
92
+const (
93
+	IDLE        BGPState = 1
94
+	CONNECT     BGPState = 2
95
+	ACTIVE      BGPState = 3
96
+	OPENSENT    BGPState = 4
97
+	OPENCONFIRM BGPState = 5
98
+	ESTABLISHED BGPState = 6
99
+)
100
+
101
+func packValues(values []interface{}) ([]byte, error) {
102
+	b := new(bytes.Buffer)
103
+	for _, v := range values {
104
+		err := binary.Write(b, binary.BigEndian, v)
105
+		if err != nil {
106
+			return nil, err
107
+		}
108
+	}
109
+	return b.Bytes(), nil
110
+}
111
+
112
+type MRTHeader struct {
113
+	Timestamp uint32
114
+	Type      MRTType
115
+	SubType   uint16
116
+	Len       uint32
117
+}
118
+
119
+func (h *MRTHeader) DecodeFromBytes(data []byte) error {
120
+	if len(data) < MRT_COMMON_HEADER_LEN {
121
+		return fmt.Errorf("not all MRTHeader bytes are available. expected: %d, actual: %d", MRT_COMMON_HEADER_LEN, len(data))
122
+	}
123
+	h.Timestamp = binary.BigEndian.Uint32(data[:4])
124
+	h.Type = MRTType(binary.BigEndian.Uint16(data[4:6]))
125
+	h.SubType = binary.BigEndian.Uint16(data[6:8])
126
+	h.Len = binary.BigEndian.Uint32(data[8:12])
127
+	return nil
128
+}
129
+
130
+func (h *MRTHeader) Serialize() ([]byte, error) {
131
+	return packValues([]interface{}{h.Timestamp, h.Type, h.SubType, h.Len})
132
+}
133
+
134
+func NewMRTHeader(timestamp uint32, t MRTType, subtype MRTSubTyper, l uint32) (*MRTHeader, error) {
135
+	return &MRTHeader{
136
+		Timestamp: timestamp,
137
+		Type:      t,
138
+		SubType:   subtype.ToUint16(),
139
+		Len:       l,
140
+	}, nil
141
+}
142
+
143
+func (h *MRTHeader) GetTime() time.Time {
144
+	t := int64(h.Timestamp)
145
+	return time.Unix(t, 0)
146
+}
147
+
148
+type MRTMessage struct {
149
+	Header MRTHeader
150
+	Body   Body
151
+}
152
+
153
+func (m *MRTMessage) Serialize() ([]byte, error) {
154
+	buf, err := m.Body.Serialize()
155
+	if err != nil {
156
+		return nil, err
157
+	}
158
+	m.Header.Len = uint32(len(buf))
159
+	bbuf, err := m.Header.Serialize()
160
+	if err != nil {
161
+		return nil, err
162
+	}
163
+	return append(bbuf, buf...), nil
164
+}
165
+
166
+func NewMRTMessage(timestamp uint32, t MRTType, subtype MRTSubTyper, body Body) (*MRTMessage, error) {
167
+	header, err := NewMRTHeader(timestamp, t, subtype, 0)
168
+	if err != nil {
169
+		return nil, err
170
+	}
171
+	return &MRTMessage{
172
+		Header: *header,
173
+		Body:   body,
174
+	}, nil
175
+}
176
+
177
+type Body interface {
178
+	DecodeFromBytes([]byte) error
179
+	Serialize() ([]byte, error)
180
+}
181
+
182
+type Peer struct {
183
+	Type      uint8
184
+	BgpId     net.IP
185
+	IpAddress net.IP
186
+	AS        uint32
187
+}
188
+
189
+func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
190
+	notAllBytesAvail := fmt.Errorf("not all Peer bytes are available")
191
+	if len(data) < 5 {
192
+		return nil, notAllBytesAvail
193
+	}
194
+	p.Type = uint8(data[0])
195
+	p.BgpId = net.IP(data[1:5])
196
+	data = data[5:]
197
+
198
+	if p.Type&1 > 0 {
199
+		if len(data) < 16 {
200
+			return nil, notAllBytesAvail
201
+		}
202
+		p.IpAddress = net.IP(data[:16])
203
+		data = data[16:]
204
+	} else {
205
+		if len(data) < 4 {
206
+			return nil, notAllBytesAvail
207
+		}
208
+		p.IpAddress = net.IP(data[:4])
209
+		data = data[4:]
210
+	}
211
+
212
+	if p.Type&(1<<1) > 0 {
213
+		if len(data) < 4 {
214
+			return nil, notAllBytesAvail
215
+		}
216
+		p.AS = binary.BigEndian.Uint32(data[:4])
217
+		data = data[4:]
218
+	} else {
219
+		if len(data) < 2 {
220
+			return nil, notAllBytesAvail
221
+		}
222
+		p.AS = uint32(binary.BigEndian.Uint16(data[:2]))
223
+		data = data[2:]
224
+	}
225
+
226
+	return data, nil
227
+}
228
+
229
+func (p *Peer) Serialize() ([]byte, error) {
230
+	var err error
231
+	var bbuf []byte
232
+	buf := make([]byte, 5)
233
+	buf[0] = uint8(p.Type)
234
+	copy(buf[1:], p.BgpId.To4())
235
+	if p.Type&1 > 0 {
236
+		buf = append(buf, p.IpAddress.To16()...)
237
+	} else {
238
+		buf = append(buf, p.IpAddress.To4()...)
239
+	}
240
+	if p.Type&(1<<1) > 0 {
241
+		bbuf, err = packValues([]interface{}{p.AS})
242
+	} else {
243
+		if p.AS > uint32(math.MaxUint16) {
244
+			return nil, fmt.Errorf("AS number is beyond 2 octet. %d > %d", p.AS, math.MaxUint16)
245
+		}
246
+		bbuf, err = packValues([]interface{}{uint16(p.AS)})
247
+	}
248
+	if err != nil {
249
+		return nil, err
250
+	}
251
+	return append(buf, bbuf...), nil
252
+}
253
+
254
+func NewPeer(bgpid string, ipaddr string, asn uint32, isAS4 bool) *Peer {
255
+	t := 0
256
+	addr := net.ParseIP(ipaddr).To4()
257
+	if addr == nil {
258
+		t |= 1
259
+		addr = net.ParseIP(ipaddr).To16()
260
+	}
261
+	if isAS4 {
262
+		t |= (1 << 1)
263
+	}
264
+	return &Peer{
265
+		Type:      uint8(t),
266
+		BgpId:     net.ParseIP(bgpid).To4(),
267
+		IpAddress: addr,
268
+		AS:        asn,
269
+	}
270
+}
271
+
272
+func (p *Peer) String() string {
273
+	return fmt.Sprintf("PEER ENTRY: ID [%s] Addr [%s] AS [%d]", p.BgpId, p.IpAddress, p.AS)
274
+}
275
+
276
+type PeerIndexTable struct {
277
+	CollectorBgpId net.IP
278
+	ViewName       string
279
+	Peers          []*Peer
280
+}
281
+
282
+func (t *PeerIndexTable) DecodeFromBytes(data []byte) error {
283
+	notAllBytesAvail := fmt.Errorf("not all PeerIndexTable bytes are available")
284
+	if len(data) < 6 {
285
+		return notAllBytesAvail
286
+	}
287
+	t.CollectorBgpId = net.IP(data[:4])
288
+	viewLen := binary.BigEndian.Uint16(data[4:6])
289
+	if len(data) < 6+int(viewLen) {
290
+		return notAllBytesAvail
291
+	}
292
+	t.ViewName = string(data[6 : 6+viewLen])
293
+
294
+	data = data[6+viewLen:]
295
+
296
+	if len(data) < 2 {
297
+		return notAllBytesAvail
298
+	}
299
+	peerNum := binary.BigEndian.Uint16(data[:2])
300
+	data = data[2:]
301
+	t.Peers = make([]*Peer, 0, peerNum)
302
+	var err error
303
+	for i := 0; i < int(peerNum); i++ {
304
+		p := &Peer{}
305
+		data, err = p.DecodeFromBytes(data)
306
+		if err != nil {
307
+			return err
308
+		}
309
+		t.Peers = append(t.Peers, p)
310
+	}
311
+
312
+	return nil
313
+}
314
+
315
+func (t *PeerIndexTable) Serialize() ([]byte, error) {
316
+	buf := make([]byte, 8+len(t.ViewName))
317
+	copy(buf, t.CollectorBgpId.To4())
318
+	binary.BigEndian.PutUint16(buf[4:], uint16(len(t.ViewName)))
319
+	copy(buf[6:], t.ViewName)
320
+	binary.BigEndian.PutUint16(buf[6+len(t.ViewName):], uint16(len(t.Peers)))
321
+	for _, peer := range t.Peers {
322
+		bbuf, err := peer.Serialize()
323
+		if err != nil {
324
+			return nil, err
325
+		}
326
+		buf = append(buf, bbuf...)
327
+	}
328
+	return buf, nil
329
+}
330
+
331
+func NewPeerIndexTable(bgpid string, viewname string, peers []*Peer) *PeerIndexTable {
332
+	return &PeerIndexTable{
333
+		CollectorBgpId: net.ParseIP(bgpid).To4(),
334
+		ViewName:       viewname,
335
+		Peers:          peers,
336
+	}
337
+}
338
+
339
+func (t *PeerIndexTable) String() string {
340
+	return fmt.Sprintf("PEER_INDEX_TABLE: CollectorBgpId [%s] ViewName [%s] Peers [%s]", t.CollectorBgpId, t.ViewName, t.Peers)
341
+}
342
+
343
+type RibEntry struct {
344
+	PeerIndex      uint16
345
+	OriginatedTime uint32
346
+	PathAttributes []PathAttributeInterface
347
+}
348
+
349
+func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
350
+	notAllBytesAvail := fmt.Errorf("not all RibEntry bytes are available")
351
+	if len(data) < 8 {
352
+		return nil, notAllBytesAvail
353
+	}
354
+	e.PeerIndex = binary.BigEndian.Uint16(data[:2])
355
+	e.OriginatedTime = binary.BigEndian.Uint32(data[2:6])
356
+	totalLen := binary.BigEndian.Uint16(data[6:8])
357
+	data = data[8:]
358
+	for attrLen := totalLen; attrLen > 0; {
359
+		p, err := GetPathAttribute(data)
360
+		if err != nil {
361
+			return nil, err
362
+		}
363
+		err = p.DecodeFromBytes(data)
364
+		if err != nil {
365
+			return nil, err
366
+		}
367
+		attrLen -= uint16(p.Len())
368
+		if len(data) < p.Len() {
369
+			return nil, notAllBytesAvail
370
+		}
371
+		data = data[p.Len():]
372
+		e.PathAttributes = append(e.PathAttributes, p)
373
+	}
374
+	return data, nil
375
+}
376
+
377
+func (e *RibEntry) Serialize() ([]byte, error) {
378
+	buf := make([]byte, 8)
379
+	binary.BigEndian.PutUint16(buf, e.PeerIndex)
380
+	binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime)
381
+	totalLen := 0
382
+	binary.BigEndian.PutUint16(buf[6:], uint16(totalLen))
383
+	for _, pattr := range e.PathAttributes {
384
+		// TODO special modification is needed for MP_REACH_NLRI
385
+		// but also Quagga doesn't implement this.
386
+		//
387
+		// RFC 6396 4.3.4
388
+		// There is one exception to the encoding of BGP attributes for the BGP
389
+		// MP_REACH_NLRI attribute (BGP Type Code 14).
390
+		// Since the AFI, SAFI, and NLRI information is already encoded
391
+		// in the RIB Entry Header or RIB_GENERIC Entry Header,
392
+		// only the Next Hop Address Length and Next Hop Address fields are included.
393
+
394
+		bbuf, err := pattr.Serialize()
395
+		if err != nil {
396
+			return nil, err
397
+		}
398
+		buf = append(buf, bbuf...)
399
+		totalLen += len(bbuf)
400
+	}
401
+	binary.BigEndian.PutUint16(buf[6:], uint16(totalLen))
402
+	return buf, nil
403
+}
404
+
405
+func NewRibEntry(index uint16, time uint32, pathattrs []PathAttributeInterface) *RibEntry {
406
+	return &RibEntry{
407
+		PeerIndex:      index,
408
+		OriginatedTime: time,
409
+		PathAttributes: pathattrs,
410
+	}
411
+}
412
+
413
+func (e *RibEntry) String() string {
414
+	return fmt.Sprintf("RIB_ENTRY: PeerIndex [%d] OriginatedTime [%d] PathAttrs [%v]", e.PeerIndex, e.OriginatedTime, e.PathAttributes)
415
+}
416
+
417
+type Rib struct {
418
+	SequenceNumber uint32
419
+	Prefix         AddrPrefixInterface
420
+	Entries        []*RibEntry
421
+	RouteFamily    RouteFamily
422
+}
423
+
424
+func (u *Rib) DecodeFromBytes(data []byte) error {
425
+	if len(data) < 4 {
426
+		return fmt.Errorf("Not all RibIpv4Unicast message bytes available")
427
+	}
428
+	u.SequenceNumber = binary.BigEndian.Uint32(data[:4])
429
+	data = data[4:]
430
+	afi, safi := RouteFamilyToAfiSafi(u.RouteFamily)
431
+	if afi == 0 && safi == 0 {
432
+		afi = binary.BigEndian.Uint16(data[:2])
433
+		safi = data[2]
434
+		data = data[3:]
435
+	}
436
+	prefix, err := NewPrefixFromRouteFamily(afi, safi)
437
+	if err != nil {
438
+		return err
439
+	}
440
+	err = prefix.DecodeFromBytes(data)
441
+	if err != nil {
442
+		return err
443
+	}
444
+	u.Prefix = prefix
445
+	data = data[prefix.Len():]
446
+	entryNum := binary.BigEndian.Uint16(data[:2])
447
+	data = data[2:]
448
+	u.Entries = make([]*RibEntry, 0, entryNum)
449
+	for i := 0; i < int(entryNum); i++ {
450
+		e := &RibEntry{}
451
+		data, err = e.DecodeFromBytes(data)
452
+		if err != nil {
453
+			return err
454
+		}
455
+		u.Entries = append(u.Entries, e)
456
+	}
457
+	return nil
458
+}
459
+
460
+func (u *Rib) Serialize() ([]byte, error) {
461
+	buf := make([]byte, 4)
462
+	binary.BigEndian.PutUint32(buf, u.SequenceNumber)
463
+	rf := AfiSafiToRouteFamily(u.Prefix.AFI(), u.Prefix.SAFI())
464
+	switch rf {
465
+	case RF_IPv4_UC, RF_IPv4_MC, RF_IPv6_UC, RF_IPv6_MC:
466
+	default:
467
+		bbuf := make([]byte, 0, 2)
468
+		binary.BigEndian.PutUint16(bbuf, u.Prefix.AFI())
469
+		buf = append(buf, bbuf...)
470
+		buf = append(buf, u.Prefix.SAFI())
471
+	}
472
+	bbuf, err := u.Prefix.Serialize()
473
+	if err != nil {
474
+		return nil, err
475
+	}
476
+	buf = append(buf, bbuf...)
477
+	bbuf, err = packValues([]interface{}{uint16(len(u.Entries))})
478
+	if err != nil {
479
+		return nil, err
480
+	}
481
+	buf = append(buf, bbuf...)
482
+	for _, entry := range u.Entries {
483
+		bbuf, err = entry.Serialize()
484
+		if err != nil {
485
+			return nil, err
486
+		}
487
+		buf = append(buf, bbuf...)
488
+	}
489
+	return buf, nil
490
+}
491
+
492
+func NewRib(seq uint32, prefix AddrPrefixInterface, entries []*RibEntry) *Rib {
493
+	rf := AfiSafiToRouteFamily(prefix.AFI(), prefix.SAFI())
494
+	return &Rib{
495
+		SequenceNumber: seq,
496
+		Prefix:         prefix,
497
+		Entries:        entries,
498
+		RouteFamily:    rf,
499
+	}
500
+}
501
+
502
+func (u *Rib) String() string {
503
+	return fmt.Sprintf("RIB: Seq [%d] Prefix [%s] Entries [%s]", u.SequenceNumber, u.Prefix, u.Entries)
504
+}
505
+
506
+type BGP4MPHeader struct {
507
+	PeerAS         uint32
508
+	LocalAS        uint32
509
+	InterfaceIndex uint16
510
+	AddressFamily  uint16
511
+	PeerIpAddress  net.IP
512
+	LocalIpAddress net.IP
513
+	isAS4          bool
514
+}
515
+
516
+func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) {
517
+	if m.isAS4 && len(data) < 8 {
518
+		return nil, fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
519
+	} else if !m.isAS4 && len(data) < 4 {
520
+		return nil, fmt.Errorf("Not all BGP4MPMessageAS bytes available")
521
+	}
522
+
523
+	if m.isAS4 {
524
+		m.PeerAS = binary.BigEndian.Uint32(data[:4])
525
+		m.LocalAS = binary.BigEndian.Uint32(data[4:8])
526
+		data = data[8:]
527
+	} else {
528
+		m.PeerAS = uint32(binary.BigEndian.Uint16(data[:2]))
529
+		m.LocalAS = uint32(binary.BigEndian.Uint16(data[2:4]))
530
+		data = data[4:]
531
+	}
532
+	m.InterfaceIndex = binary.BigEndian.Uint16(data[:2])
533
+	m.AddressFamily = binary.BigEndian.Uint16(data[2:4])
534
+	switch m.AddressFamily {
535
+	case AFI_IP:
536
+		m.PeerIpAddress = net.IP(data[4:8]).To4()
537
+		m.LocalIpAddress = net.IP(data[8:12]).To4()
538
+		data = data[12:]
539
+	case AFI_IP6:
540
+		m.PeerIpAddress = net.IP(data[4:20])
541
+		m.LocalIpAddress = net.IP(data[20:36])
542
+		data = data[36:]
543
+	default:
544
+		return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily)
545
+	}
546
+	return data, nil
547
+}
548
+
549
+func (m *BGP4MPHeader) serialize() ([]byte, error) {
550
+	var values []interface{}
551
+	if m.isAS4 {
552
+		values = []interface{}{m.PeerAS, m.LocalAS, m.InterfaceIndex, m.AddressFamily}
553
+	} else {
554
+		values = []interface{}{uint16(m.PeerAS), uint16(m.LocalAS), m.InterfaceIndex, m.AddressFamily}
555
+	}
556
+	buf, err := packValues(values)
557
+	if err != nil {
558
+		return nil, err
559
+	}
560
+	var bbuf []byte
561
+	switch m.AddressFamily {
562
+	case AFI_IP:
563
+		bbuf = make([]byte, 8)
564
+		copy(bbuf, m.PeerIpAddress.To4())
565
+		copy(bbuf[4:], m.LocalIpAddress.To4())
566
+	case AFI_IP6:
567
+		bbuf = make([]byte, 32)
568
+		copy(bbuf, m.PeerIpAddress)
569
+		copy(bbuf[16:], m.LocalIpAddress)
570
+	default:
571
+		return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily)
572
+	}
573
+	return append(buf, bbuf...), nil
574
+}
575
+
576
+func newBGP4MPHeader(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool) (*BGP4MPHeader, error) {
577
+	var af uint16
578
+	paddr := net.ParseIP(peerip).To4()
579
+	laddr := net.ParseIP(localip).To4()
580
+	if paddr != nil && laddr != nil {
581
+		af = AFI_IP
582
+	} else {
583
+		paddr = net.ParseIP(peerip).To16()
584
+		laddr = net.ParseIP(localip).To16()
585
+		if paddr != nil && laddr != nil {
586
+			af = AFI_IP6
587
+		} else {
588
+			return nil, fmt.Errorf("Peer IP Address and Local IP Address must have the same address family")
589
+		}
590
+	}
591
+	return &BGP4MPHeader{
592
+		PeerAS:         peeras,
593
+		LocalAS:        localas,
594
+		InterfaceIndex: intfindex,
595
+		AddressFamily:  af,
596
+		PeerIpAddress:  paddr,
597
+		LocalIpAddress: laddr,
598
+		isAS4:          isAS4,
599
+	}, nil
600
+}
601
+
602
+type BGP4MPStateChange struct {
603
+	*BGP4MPHeader
604
+	OldState BGPState
605
+	NewState BGPState
606
+}
607
+
608
+func (m *BGP4MPStateChange) DecodeFromBytes(data []byte) error {
609
+	rest, err := m.decodeFromBytes(data)
610
+	if err != nil {
611
+		return err
612
+	}
613
+	if len(rest) < 4 {
614
+		return fmt.Errorf("Not all BGP4MPStateChange bytes available")
615
+	}
616
+	m.OldState = BGPState(binary.BigEndian.Uint16(rest[:2]))
617
+	m.NewState = BGPState(binary.BigEndian.Uint16(rest[2:4]))
618
+	return nil
619
+}
620
+
621
+func (m *BGP4MPStateChange) Serialize() ([]byte, error) {
622
+	buf, err := m.serialize()
623
+	if err != nil {
624
+		return nil, err
625
+	}
626
+	bbuf, err := packValues([]interface{}{m.OldState, m.NewState})
627
+	if err != nil {
628
+		return nil, err
629
+	}
630
+	return append(buf, bbuf...), nil
631
+}
632
+
633
+func NewBGP4MPStateChange(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, oldstate, newstate BGPState) *BGP4MPStateChange {
634
+	header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4)
635
+	return &BGP4MPStateChange{
636
+		BGP4MPHeader: header,
637
+		OldState:     oldstate,
638
+		NewState:     newstate,
639
+	}
640
+}
641
+
642
+type BGP4MPMessage struct {
643
+	*BGP4MPHeader
644
+	BGPMessage        *BGPMessage
645
+	BGPMessagePayload []byte
646
+	isLocal           bool
647
+}
648
+
649
+func (m *BGP4MPMessage) DecodeFromBytes(data []byte) error {
650
+	rest, err := m.decodeFromBytes(data)
651
+	if err != nil {
652
+		return err
653
+	}
654
+
655
+	if len(rest) < BGP_HEADER_LENGTH {
656
+		return fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
657
+	}
658
+
659
+	msg, err := ParseBGPMessage(rest)
660
+	if err != nil {
661
+		return err
662
+	}
663
+	m.BGPMessage = msg
664
+	return nil
665
+}
666
+
667
+func (m *BGP4MPMessage) Serialize() ([]byte, error) {
668
+	buf, err := m.serialize()
669
+	if err != nil {
670
+		return nil, err
671
+	}
672
+	if m.BGPMessagePayload != nil {
673
+		return append(buf, m.BGPMessagePayload...), nil
674
+	}
675
+	bbuf, err := m.BGPMessage.Serialize()
676
+	if err != nil {
677
+		return nil, err
678
+	}
679
+	return append(buf, bbuf...), nil
680
+}
681
+
682
+func NewBGP4MPMessage(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *BGPMessage) *BGP4MPMessage {
683
+	header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4)
684
+	return &BGP4MPMessage{
685
+		BGP4MPHeader: header,
686
+		BGPMessage:   msg,
687
+	}
688
+}
689
+
690
+func NewBGP4MPMessageLocal(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *BGPMessage) *BGP4MPMessage {
691
+	header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4)
692
+	return &BGP4MPMessage{
693
+		BGP4MPHeader: header,
694
+		BGPMessage:   msg,
695
+		isLocal:      true,
696
+	}
697
+}
698
+
699
+func (m *BGP4MPMessage) String() string {
700
+	title := "BGP4MP_MSG"
701
+	if m.isAS4 {
702
+		title += "_AS4"
703
+	}
704
+	if m.isLocal {
705
+		title += "_LOCAL"
706
+	}
707
+	return fmt.Sprintf("%s: PeerAS [%d] LocalAS [%d] InterfaceIndex [%d] PeerIP [%s] LocalIP [%s] BGPMessage [%v]", title, m.PeerAS, m.LocalAS, m.InterfaceIndex, m.PeerIpAddress, m.LocalIpAddress, m.BGPMessage)
708
+}
709
+
710
+//This function can be passed into a bufio.Scanner.Split() to read buffered mrt msgs
711
+func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) {
712
+	if atEOF && len(data) == 0 {
713
+		return 0, nil, nil
714
+	}
715
+	if cap(data) < MRT_COMMON_HEADER_LEN { // read more
716
+		return 0, nil, nil
717
+	}
718
+	//this reads the data
719
+	hdr := &MRTHeader{}
720
+	errh := hdr.DecodeFromBytes(data[:MRT_COMMON_HEADER_LEN])
721
+	if errh != nil {
722
+		return 0, nil, errh
723
+	}
724
+	totlen := int(hdr.Len + MRT_COMMON_HEADER_LEN)
725
+	if len(data) < totlen { //need to read more
726
+		return 0, nil, nil
727
+	}
728
+	return totlen, data[0:totlen], nil
729
+}
730
+
731
+func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
732
+	if len(data) < int(h.Len) {
733
+		return nil, fmt.Errorf("Not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data))
734
+	}
735
+	msg := &MRTMessage{Header: *h}
736
+	switch h.Type {
737
+	case TABLE_DUMPv2:
738
+		subType := MRTSubTypeTableDumpv2(h.SubType)
739
+		rf := RouteFamily(0)
740
+		switch subType {
741
+		case PEER_INDEX_TABLE:
742
+			msg.Body = &PeerIndexTable{}
743
+		case RIB_IPV4_UNICAST:
744
+			rf = RF_IPv4_UC
745
+		case RIB_IPV4_MULTICAST:
746
+			rf = RF_IPv4_MC
747
+		case RIB_IPV6_UNICAST:
748
+			rf = RF_IPv6_UC
749
+		case RIB_IPV6_MULTICAST:
750
+			rf = RF_IPv6_MC
751
+		case RIB_GENERIC:
752
+		default:
753
+			return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v\n", subType)
754
+		}
755
+
756
+		if subType != PEER_INDEX_TABLE {
757
+			msg.Body = &Rib{
758
+				RouteFamily: rf,
759
+			}
760
+		}
761
+	case BGP4MP:
762
+		subType := MRTSubTypeBGP4MP(h.SubType)
763
+		isAS4 := true
764
+		switch subType {
765
+		case STATE_CHANGE:
766
+			isAS4 = false
767
+			fallthrough
768
+		case STATE_CHANGE_AS4:
769
+			msg.Body = &BGP4MPStateChange{
770
+				BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4},
771
+			}
772
+		case MESSAGE:
773
+			isAS4 = false
774
+			fallthrough
775
+		case MESSAGE_AS4:
776
+			msg.Body = &BGP4MPMessage{
777
+				BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4},
778
+			}
779
+		case MESSAGE_LOCAL:
780
+			isAS4 = false
781
+			fallthrough
782
+		case MESSAGE_AS4_LOCAL:
783
+			msg.Body = &BGP4MPMessage{
784
+				BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4},
785
+				isLocal:      true,
786
+			}
787
+		default:
788
+			return nil, fmt.Errorf("unsupported bgp4mp subtype: %v\n", subType)
789
+		}
790
+	default:
791
+		return nil, fmt.Errorf("unsupported type: %v\n", h.Type)
792
+	}
793
+	err := msg.Body.DecodeFromBytes(data)
794
+	if err != nil {
795
+		return nil, err
796
+	}
797
+	return msg, nil
798
+}

+ 63
- 0
vendor/github.com/osrg/gobgp/packet/routefamily_string.go Bestand weergeven

@@ -0,0 +1,63 @@
1
+// generated by stringer -type=RouteFamily bgp.go validate.go constant.go; DO NOT EDIT
2
+
3
+package bgp
4
+
5
+import "fmt"
6
+
7
+const (
8
+	_RouteFamily_name_0 = "RF_IPv4_UCRF_IPv4_MC"
9
+	_RouteFamily_name_1 = "RF_IPv4_MPLS"
10
+	_RouteFamily_name_2 = "RF_ENCAP"
11
+	_RouteFamily_name_3 = "RF_IPv4_VPNRF_IPv4_VPN_MC"
12
+	_RouteFamily_name_4 = "RF_RTC_UCRF_FS_IPv4_UCRF_FS_IPv4_VPN"
13
+	_RouteFamily_name_5 = "RF_IPv6_UCRF_IPv6_MC"
14
+	_RouteFamily_name_6 = "RF_IPv6_MPLS"
15
+	_RouteFamily_name_7 = "RF_IPv6_VPNRF_IPv6_VPN_MC"
16
+	_RouteFamily_name_8 = "RF_VPLS"
17
+	_RouteFamily_name_9 = "RF_EVPN"
18
+)
19
+
20
+var (
21
+	_RouteFamily_index_0 = [...]uint8{0, 10, 20}
22
+	_RouteFamily_index_1 = [...]uint8{0, 12}
23
+	_RouteFamily_index_2 = [...]uint8{0, 8}
24
+	_RouteFamily_index_3 = [...]uint8{0, 11, 25}
25
+	_RouteFamily_index_4 = [...]uint8{0, 9, 22, 36}
26
+	_RouteFamily_index_5 = [...]uint8{0, 10, 20}
27
+	_RouteFamily_index_6 = [...]uint8{0, 12}
28
+	_RouteFamily_index_7 = [...]uint8{0, 11, 25}
29
+	_RouteFamily_index_8 = [...]uint8{0, 7}
30
+	_RouteFamily_index_9 = [...]uint8{0, 7}
31
+)
32
+
33
+func (i RouteFamily) String() string {
34
+	switch {
35
+	case 65537 <= i && i <= 65538:
36
+		i -= 65537
37
+		return _RouteFamily_name_0[_RouteFamily_index_0[i]:_RouteFamily_index_0[i+1]]
38
+	case i == 65540:
39
+		return _RouteFamily_name_1
40
+	case i == 65543:
41
+		return _RouteFamily_name_2
42
+	case 65664 <= i && i <= 65665:
43
+		i -= 65664
44
+		return _RouteFamily_name_3[_RouteFamily_index_3[i]:_RouteFamily_index_3[i+1]]
45
+	case 65668 <= i && i <= 65670:
46
+		i -= 65668
47
+		return _RouteFamily_name_4[_RouteFamily_index_4[i]:_RouteFamily_index_4[i+1]]
48
+	case 131073 <= i && i <= 131074:
49
+		i -= 131073
50
+		return _RouteFamily_name_5[_RouteFamily_index_5[i]:_RouteFamily_index_5[i+1]]
51
+	case i == 131076:
52
+		return _RouteFamily_name_6
53
+	case 131200 <= i && i <= 131201:
54
+		i -= 131200
55
+		return _RouteFamily_name_7[_RouteFamily_index_7[i]:_RouteFamily_index_7[i+1]]
56
+	case i == 1638465:
57
+		return _RouteFamily_name_8
58
+	case i == 1638470:
59
+		return _RouteFamily_name_9
60
+	default:
61
+		return fmt.Sprintf("RouteFamily(%d)", i)
62
+	}
63
+}

+ 392
- 0
vendor/github.com/osrg/gobgp/packet/rtr.go Bestand weergeven

@@ -0,0 +1,392 @@
1
+// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+//    http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
+// implied.
13
+// See the License for the specific language governing permissions and
14
+// limitations under the License.
15
+
16
+package bgp
17
+
18
+import (
19
+	"encoding/binary"
20
+	"fmt"
21
+	"net"
22
+)
23
+
24
+const (
25
+	RPKI_DEFAULT_PORT = 323
26
+)
27
+
28
+const (
29
+	RTR_SERIAL_NOTIFY = iota
30
+	RTR_SERIAL_QUERY
31
+	RTR_RESET_QUERY
32
+	RTR_CACHE_RESPONSE
33
+	RTR_IPV4_PREFIX
34
+	_
35
+	RTR_IPV6_PREFIX
36
+	RTR_END_OF_DATA
37
+	RTR_CACHE_RESET
38
+	_
39
+	RTR_ERROR_REPORT
40
+)
41
+
42
+const (
43
+	RTR_SERIAL_NOTIFY_LEN         = 12
44
+	RTR_SERIAL_QUERY_LEN          = 12
45
+	RTR_RESET_QUERY_LEN           = 8
46
+	RTR_CACHE_RESPONSE_LEN        = 8
47
+	RTR_IPV4_PREFIX_LEN           = 20
48
+	RTR_IPV6_PREFIX_LEN           = 32
49
+	RTR_END_OF_DATA_LEN           = 12
50
+	RTR_CACHE_RESET_LEN           = 8
51
+	RTR_MIN_LEN                   = 8
52
+	RTR_ERROR_REPORT_ERR_PDU_LEN  = 4
53
+	RTR_ERROR_REPORT_ERR_TEXT_LEN = 4
54
+)
55
+
56
+const (
57
+	WITHDRAWAL uint8 = iota
58
+	ANNOUNCEMENT
59
+)
60
+
61
+const (
62
+	CORRUPT_DATA uint16 = iota
63
+	INTERNAL_ERROR
64
+	NO_DATA_AVAILABLE
65
+	INVALID_REQUEST
66
+	UNSUPPORTED_PROTOCOL_VERSION
67
+	UNSUPPORTED_PDU_TYPE
68
+	WITHDRAWAL_OF_UNKNOWN_RECORD
69
+	DUPLICATE_ANNOUNCEMENT_RECORD
70
+)
71
+
72
+type RTRMessage interface {
73
+	DecodeFromBytes([]byte) error
74
+	Serialize() ([]byte, error)
75
+}
76
+
77
+type RTRCommon struct {
78
+	Version      uint8
79
+	Type         uint8
80
+	SessionID    uint16
81
+	Len          uint32
82
+	SerialNumber uint32
83
+}
84
+
85
+func (m *RTRCommon) DecodeFromBytes(data []byte) error {
86
+	m.Version = data[0]
87
+	m.Type = data[1]
88
+	m.SessionID = binary.BigEndian.Uint16(data[2:4])
89
+	m.Len = binary.BigEndian.Uint32(data[4:8])
90
+	m.SerialNumber = binary.BigEndian.Uint32(data[8:12])
91
+	return nil
92
+}
93
+
94
+func (m *RTRCommon) Serialize() ([]byte, error) {
95
+	data := make([]byte, m.Len)
96
+	data[0] = m.Version
97
+	data[1] = m.Type
98
+	binary.BigEndian.PutUint16(data[2:4], m.SessionID)
99
+	binary.BigEndian.PutUint32(data[4:8], m.Len)
100
+	binary.BigEndian.PutUint32(data[8:12], m.SerialNumber)
101
+	return data, nil
102
+}
103
+
104
+type RTRSerialNotify struct {
105
+	RTRCommon
106
+}
107
+
108
+func NewRTRSerialNotify(id uint16, sn uint32) *RTRSerialNotify {
109
+	return &RTRSerialNotify{
110
+		RTRCommon{
111
+			Type:         RTR_SERIAL_NOTIFY,
112
+			SessionID:    id,
113
+			Len:          RTR_SERIAL_NOTIFY_LEN,
114
+			SerialNumber: sn,
115
+		},
116
+	}
117
+}
118
+
119
+type RTRSerialQuery struct {
120
+	RTRCommon
121
+}
122
+
123
+func NewRTRSerialQuery(id uint16, sn uint32) *RTRSerialQuery {
124
+	return &RTRSerialQuery{
125
+		RTRCommon{
126
+			Type:         RTR_SERIAL_QUERY,
127
+			SessionID:    id,
128
+			Len:          RTR_SERIAL_QUERY_LEN,
129
+			SerialNumber: sn,
130
+		},
131
+	}
132
+}
133
+
134
+type RTRReset struct {
135
+	Version uint8
136
+	Type    uint8
137
+	Len     uint32
138
+}
139
+
140
+func (m *RTRReset) DecodeFromBytes(data []byte) error {
141
+	m.Version = data[0]
142
+	m.Type = data[1]
143
+	m.Len = binary.BigEndian.Uint32(data[4:8])
144
+	return nil
145
+}
146
+
147
+func (m *RTRReset) Serialize() ([]byte, error) {
148
+	data := make([]byte, m.Len)
149
+	data[0] = m.Version
150
+	data[1] = m.Type
151
+	binary.BigEndian.PutUint32(data[4:8], m.Len)
152
+	return data, nil
153
+}
154
+
155
+type RTRResetQuery struct {
156
+	RTRReset
157
+}
158
+
159
+func NewRTRResetQuery() *RTRResetQuery {
160
+	return &RTRResetQuery{
161
+		RTRReset{
162
+			Type: RTR_RESET_QUERY,
163
+			Len:  RTR_RESET_QUERY_LEN,
164
+		},
165
+	}
166
+}
167
+
168
+type RTRCacheResponse struct {
169
+	Version   uint8
170
+	Type      uint8
171
+	SessionID uint16
172
+	Len       uint32
173
+}
174
+
175
+func (m *RTRCacheResponse) DecodeFromBytes(data []byte) error {
176
+	m.Version = data[0]
177
+	m.Type = data[1]
178
+	m.SessionID = binary.BigEndian.Uint16(data[2:4])
179
+	m.Len = binary.BigEndian.Uint32(data[4:8])
180
+	return nil
181
+}
182
+
183
+func (m *RTRCacheResponse) Serialize() ([]byte, error) {
184
+	data := make([]byte, m.Len)
185
+	data[0] = m.Version
186
+	data[1] = m.Type
187
+	binary.BigEndian.PutUint16(data[2:4], m.SessionID)
188
+	binary.BigEndian.PutUint32(data[4:8], m.Len)
189
+	return data, nil
190
+}
191
+
192
+func NewRTRCacheResponse(id uint16) *RTRCacheResponse {
193
+	return &RTRCacheResponse{
194
+		Type:      RTR_CACHE_RESPONSE,
195
+		SessionID: id,
196
+		Len:       RTR_CACHE_RESPONSE_LEN,
197
+	}
198
+}
199
+
200
+type RTRIPPrefix struct {
201
+	Version   uint8
202
+	Type      uint8
203
+	Len       uint32
204
+	Flags     uint8
205
+	PrefixLen uint8
206
+	MaxLen    uint8
207
+	Prefix    net.IP
208
+	AS        uint32
209
+}
210
+
211
+func (m *RTRIPPrefix) DecodeFromBytes(data []byte) error {
212
+	m.Version = data[0]
213
+	m.Type = data[1]
214
+	m.Len = binary.BigEndian.Uint32(data[4:8])
215
+	m.Flags = data[8]
216
+	m.PrefixLen = data[9]
217
+	m.MaxLen = data[10]
218
+	if m.Type == RTR_IPV4_PREFIX {
219
+		m.Prefix = net.IP(data[12:16]).To4()
220
+		m.AS = binary.BigEndian.Uint32(data[16:20])
221
+	} else {
222
+		m.Prefix = net.IP(data[12:28]).To16()
223
+		m.AS = binary.BigEndian.Uint32(data[28:32])
224
+	}
225
+	return nil
226
+}
227
+
228
+func (m *RTRIPPrefix) Serialize() ([]byte, error) {
229
+	data := make([]byte, m.Len)
230
+	data[0] = m.Version
231
+	data[1] = m.Type
232
+	binary.BigEndian.PutUint32(data[4:8], m.Len)
233
+	data[8] = m.Flags
234
+	data[9] = m.PrefixLen
235
+	data[10] = m.MaxLen
236
+	if m.Type == RTR_IPV4_PREFIX {
237
+		copy(data[12:16], m.Prefix.To4())
238
+		binary.BigEndian.PutUint32(data[16:20], m.AS)
239
+	} else {
240
+		copy(data[12:28], m.Prefix.To16())
241
+		binary.BigEndian.PutUint32(data[28:32], m.AS)
242
+	}
243
+	return data, nil
244
+}
245
+
246
+func NewRTRIPPrefix(prefix net.IP, prefixLen, maxLen uint8, as uint32, flags uint8) *RTRIPPrefix {
247
+	var pduType uint8
248
+	var pduLen uint32
249
+	if prefix.To4() != nil && prefixLen <= 32 {
250
+		pduType = RTR_IPV4_PREFIX
251
+		pduLen = RTR_IPV4_PREFIX_LEN
252
+	} else {
253
+		pduType = RTR_IPV6_PREFIX
254
+		pduLen = RTR_IPV6_PREFIX_LEN
255
+	}
256
+
257
+	return &RTRIPPrefix{
258
+		Type:      pduType,
259
+		Len:       pduLen,
260
+		Flags:     flags,
261
+		PrefixLen: prefixLen,
262
+		MaxLen:    maxLen,
263
+		Prefix:    prefix,
264
+		AS:        as,
265
+	}
266
+}
267
+
268
+type RTREndOfData struct {
269
+	RTRCommon
270
+}
271
+
272
+func NewRTREndOfData(id uint16, sn uint32) *RTREndOfData {
273
+	return &RTREndOfData{
274
+		RTRCommon{
275
+			Type:         RTR_END_OF_DATA,
276
+			SessionID:    id,
277
+			Len:          RTR_END_OF_DATA_LEN,
278
+			SerialNumber: sn,
279
+		},
280
+	}
281
+}
282
+
283
+type RTRCacheReset struct {
284
+	RTRReset
285
+}
286
+
287
+func NewRTRCacheReset() *RTRCacheReset {
288
+	return &RTRCacheReset{
289
+		RTRReset{
290
+			Type: RTR_CACHE_RESET,
291
+			Len:  RTR_CACHE_RESET_LEN,
292
+		},
293
+	}
294
+}
295
+
296
+type RTRErrorReport struct {
297
+	Version   uint8
298
+	Type      uint8
299
+	ErrorCode uint16
300
+	Len       uint32
301
+	PDULen    uint32
302
+	PDU       []byte
303
+	TextLen   uint32
304
+	Text      []byte
305
+}
306
+
307
+func (m *RTRErrorReport) DecodeFromBytes(data []byte) error {
308
+	m.Version = data[0]
309
+	m.Type = data[1]
310
+	m.ErrorCode = binary.BigEndian.Uint16(data[2:4])
311
+	m.Len = binary.BigEndian.Uint32(data[4:8])
312
+	m.PDULen = binary.BigEndian.Uint32(data[8:12])
313
+	m.PDU = make([]byte, m.PDULen)
314
+	copy(m.PDU, data[12:12+m.PDULen])
315
+	m.TextLen = binary.BigEndian.Uint32(data[12+m.PDULen : 16+m.PDULen])
316
+	m.Text = make([]byte, m.TextLen)
317
+	copy(m.Text, data[16+m.PDULen:])
318
+	return nil
319
+}
320
+
321
+func (m *RTRErrorReport) Serialize() ([]byte, error) {
322
+	data := make([]byte, m.Len)
323
+	data[0] = m.Version
324
+	data[1] = m.Type
325
+	binary.BigEndian.PutUint16(data[2:4], m.ErrorCode)
326
+	binary.BigEndian.PutUint32(data[4:8], m.Len)
327
+	binary.BigEndian.PutUint32(data[8:12], m.PDULen)
328
+	copy(data[12:], m.PDU)
329
+	binary.BigEndian.PutUint32(data[12+m.PDULen:16+m.PDULen], m.TextLen)
330
+	copy(data[16+m.PDULen:], m.Text)
331
+	return data, nil
332
+}
333
+
334
+func NewRTRErrorReport(errCode uint16, errPDU []byte, errMsg []byte) *RTRErrorReport {
335
+	pdu := &RTRErrorReport{Type: RTR_ERROR_REPORT, ErrorCode: errCode}
336
+	if errPDU != nil {
337
+		if errPDU[1] == RTR_ERROR_REPORT {
338
+			return nil
339
+		}
340
+		pdu.PDULen = uint32(len(errPDU))
341
+		pdu.PDU = errPDU
342
+	}
343
+	if errMsg != nil {
344
+		pdu.Text = errMsg
345
+		pdu.TextLen = uint32(len(errMsg))
346
+	}
347
+	pdu.Len = uint32(RTR_MIN_LEN) + uint32(RTR_ERROR_REPORT_ERR_PDU_LEN) + pdu.PDULen + uint32(RTR_ERROR_REPORT_ERR_TEXT_LEN) + pdu.TextLen
348
+	return pdu
349
+}
350
+
351
+func SplitRTR(data []byte, atEOF bool) (advance int, token []byte, err error) {
352
+	if atEOF && len(data) == 0 || len(data) < RTR_MIN_LEN {
353
+		return 0, nil, nil
354
+	}
355
+
356
+	totalLen := binary.BigEndian.Uint32(data[4:8])
357
+	if totalLen < RTR_MIN_LEN {
358
+		return 0, nil, fmt.Errorf("Invalid length: %d", totalLen)
359
+	}
360
+	if uint32(len(data)) < totalLen {
361
+		return 0, nil, nil
362
+	}
363
+	return int(totalLen), data[0:totalLen], nil
364
+}
365
+
366
+func ParseRTR(data []byte) (RTRMessage, error) {
367
+	var msg RTRMessage
368
+	switch data[1] {
369
+	case RTR_SERIAL_NOTIFY:
370
+		msg = &RTRSerialNotify{}
371
+	case RTR_SERIAL_QUERY:
372
+		msg = &RTRSerialQuery{}
373
+	case RTR_RESET_QUERY:
374
+		msg = &RTRResetQuery{}
375
+	case RTR_CACHE_RESPONSE:
376
+		msg = &RTRCacheResponse{}
377
+	case RTR_IPV4_PREFIX:
378
+		msg = &RTRIPPrefix{}
379
+	case RTR_IPV6_PREFIX:
380
+		msg = &RTRIPPrefix{}
381
+	case RTR_END_OF_DATA:
382
+		msg = &RTREndOfData{}
383
+	case RTR_CACHE_RESET:
384
+		msg = &RTRCacheReset{}
385
+	case RTR_ERROR_REPORT:
386
+		msg = &RTRErrorReport{}
387
+	default:
388
+		return nil, fmt.Errorf("unknown RTR message type %d:", data[1])
389
+	}
390
+	err := msg.DecodeFromBytes(data)
391
+	return msg, err
392
+}

+ 221
- 0
vendor/github.com/osrg/gobgp/packet/validate.go Bestand weergeven

@@ -0,0 +1,221 @@
1
+package bgp
2
+
3
+import (
4
+	"encoding/binary"
5
+	"fmt"
6
+	"net"
7
+	"strconv"
8
+)
9
+
10
+// Validator for BGPUpdate
11
+func ValidateUpdateMsg(m *BGPUpdate, rfs map[RouteFamily]bool, doConfedCheck bool) (bool, error) {
12
+	eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
13
+	eSubCodeAttrList := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST)
14
+	eSubCodeMissing := uint8(BGP_ERROR_SUB_MISSING_WELL_KNOWN_ATTRIBUTE)
15
+
16
+	if len(m.NLRI) > 0 || len(m.WithdrawnRoutes) > 0 {
17
+		if _, ok := rfs[RF_IPv4_UC]; !ok {
18
+			return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", RF_IPv4_UC))
19
+		}
20
+	}
21
+
22
+	seen := make(map[BGPAttrType]PathAttributeInterface)
23
+	// check path attribute
24
+	for _, a := range m.PathAttributes {
25
+		// check duplication
26
+		if _, ok := seen[a.GetType()]; !ok {
27
+			seen[a.GetType()] = a
28
+		} else {
29
+			eMsg := "the path attribute apears twice. Type : " + strconv.Itoa(int(a.GetType()))
30
+			return false, NewMessageError(eCode, eSubCodeAttrList, nil, eMsg)
31
+		}
32
+
33
+		//check specific path attribute
34
+		ok, e := ValidateAttribute(a, rfs, doConfedCheck)
35
+		if !ok {
36
+			return false, e
37
+		}
38
+	}
39
+
40
+	if len(m.NLRI) > 0 {
41
+		// check the existence of well-known mandatory attributes
42
+		exist := func(attrs []BGPAttrType) (bool, BGPAttrType) {
43
+			for _, attr := range attrs {
44
+				_, ok := seen[attr]
45
+				if !ok {
46
+					return false, attr
47
+				}
48
+			}
49
+			return true, 0
50
+		}
51
+		mandatory := []BGPAttrType{BGP_ATTR_TYPE_ORIGIN, BGP_ATTR_TYPE_AS_PATH, BGP_ATTR_TYPE_NEXT_HOP}
52
+		if ok, t := exist(mandatory); !ok {
53
+			eMsg := "well-known mandatory attributes are not present. type : " + strconv.Itoa(int(t))
54
+			data := []byte{byte(t)}
55
+			return false, NewMessageError(eCode, eSubCodeMissing, data, eMsg)
56
+		}
57
+	}
58
+	return true, nil
59
+}
60
+
61
+func ValidateAttribute(a PathAttributeInterface, rfs map[RouteFamily]bool, doConfedCheck bool) (bool, error) {
62
+
63
+	eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR)
64
+	eSubCodeBadOrigin := uint8(BGP_ERROR_SUB_INVALID_ORIGIN_ATTRIBUTE)
65
+	eSubCodeBadNextHop := uint8(BGP_ERROR_SUB_INVALID_NEXT_HOP_ATTRIBUTE)
66
+	eSubCodeUnknown := uint8(BGP_ERROR_SUB_UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE)
67
+	eSubCodeMalformedAspath := uint8(BGP_ERROR_SUB_MALFORMED_AS_PATH)
68
+
69
+	checkPrefix := func(l []AddrPrefixInterface) bool {
70
+		for _, prefix := range l {
71
+			rf := AfiSafiToRouteFamily(prefix.AFI(), prefix.SAFI())
72
+			if _, ok := rfs[rf]; !ok {
73
+				return false
74
+			}
75
+		}
76
+		return true
77
+	}
78
+
79
+	switch p := a.(type) {
80
+	case *PathAttributeMpUnreachNLRI:
81
+		rf := AfiSafiToRouteFamily(p.AFI, p.SAFI)
82
+		if _, ok := rfs[rf]; !ok {
83
+			return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
84
+		}
85
+		if checkPrefix(p.Value) == false {
86
+			return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
87
+		}
88
+	case *PathAttributeMpReachNLRI:
89
+		rf := AfiSafiToRouteFamily(p.AFI, p.SAFI)
90
+		if _, ok := rfs[rf]; !ok {
91
+			return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
92
+		}
93
+		if checkPrefix(p.Value) == false {
94
+			return false, NewMessageError(0, 0, nil, fmt.Sprintf("Address-family rf %d not avalible for session", rf))
95
+		}
96
+	case *PathAttributeOrigin:
97
+		v := uint8(p.Value[0])
98
+		if v != BGP_ORIGIN_ATTR_TYPE_IGP &&
99
+			v != BGP_ORIGIN_ATTR_TYPE_EGP &&
100
+			v != BGP_ORIGIN_ATTR_TYPE_INCOMPLETE {
101
+			data, _ := a.Serialize()
102
+			eMsg := "invalid origin attribute. value : " + strconv.Itoa(int(v))
103
+			return false, NewMessageError(eCode, eSubCodeBadOrigin, data, eMsg)
104
+		}
105
+	case *PathAttributeNextHop:
106
+
107
+		isZero := func(ip net.IP) bool {
108
+			res := ip[0] & 0xff
109
+			return res == 0x00
110
+		}
111
+
112
+		isClassDorE := func(ip net.IP) bool {
113
+			res := ip[0] & 0xe0
114
+			return res == 0xe0
115
+		}
116
+
117
+		//check IP address represents host address
118
+		if p.Value.IsLoopback() || isZero(p.Value) || isClassDorE(p.Value) {
119
+			eMsg := "invalid nexthop address"
120
+			data, _ := a.Serialize()
121
+			return false, NewMessageError(eCode, eSubCodeBadNextHop, data, eMsg)
122
+		}
123
+	case *PathAttributeAsPath:
124
+		if doConfedCheck {
125
+			for _, paramIf := range p.Value {
126
+				var segType uint8
127
+				asParam, y := paramIf.(*As4PathParam)
128
+				if y {
129
+					segType = asParam.Type
130
+				} else {
131
+					segType = paramIf.(*AsPathParam).Type
132
+				}
133
+
134
+				if segType == BGP_ASPATH_ATTR_TYPE_CONFED_SET || segType == BGP_ASPATH_ATTR_TYPE_CONFED_SEQ {
135
+					return false, NewMessageError(eCode, eSubCodeMalformedAspath, nil, fmt.Sprintf("segment type confederation(%d) found", segType))
136
+				}
137
+			}
138
+		}
139
+
140
+	case *PathAttributeUnknown:
141
+		if p.getFlags()&BGP_ATTR_FLAG_OPTIONAL == 0 {
142
+			eMsg := fmt.Sprintf("unrecognized well-known attribute %s", p.GetType())
143
+			data, _ := a.Serialize()
144
+			return false, NewMessageError(eCode, eSubCodeUnknown, data, eMsg)
145
+		}
146
+	}
147
+
148
+	return true, nil
149
+
150
+}
151
+
152
+// validator for PathAttribute
153
+func ValidateFlags(t BGPAttrType, flags BGPAttrFlag) (bool, string) {
154
+
155
+	/*
156
+	 * RFC 4271 P.17 For well-known attributes, the Transitive bit MUST be set to 1.
157
+	 */
158
+	if flags&BGP_ATTR_FLAG_OPTIONAL == 0 && flags&BGP_ATTR_FLAG_TRANSITIVE == 0 {
159
+		eMsg := fmt.Sprintf("well-known attribute %s must have transitive flag 1", t)
160
+		return false, eMsg
161
+	}
162
+	/*
163
+	 * RFC 4271 P.17 For well-known attributes and for optional non-transitive attributes,
164
+	 * the Partial bit MUST be set to 0.
165
+	 */
166
+	if flags&BGP_ATTR_FLAG_OPTIONAL == 0 && flags&BGP_ATTR_FLAG_PARTIAL != 0 {
167
+		eMsg := fmt.Sprintf("well-known attribute %s must have partial bit 0", t)
168
+		return false, eMsg
169
+	}
170
+	if flags&BGP_ATTR_FLAG_OPTIONAL != 0 && flags&BGP_ATTR_FLAG_TRANSITIVE == 0 && flags&BGP_ATTR_FLAG_PARTIAL != 0 {
171
+		eMsg := fmt.Sprintf("optional non-transitive attribute %s must have partial bit 0", t)
172
+		return false, eMsg
173
+	}
174
+
175
+	// check flags are correct
176
+	if f, ok := pathAttrFlags[t]; ok {
177
+		if f != flags & ^BGP_ATTR_FLAG_EXTENDED_LENGTH & ^BGP_ATTR_FLAG_PARTIAL {
178
+			eMsg := fmt.Sprintf("flags are invalid. attribute type: %s, expect: %s, actual: %s", t, f, flags)
179
+			return false, eMsg
180
+		}
181
+	}
182
+	return true, ""
183
+}
184
+
185
+func ValidateBGPMessage(m *BGPMessage) error {
186
+	if m.Header.Len > BGP_MAX_MESSAGE_LENGTH {
187
+		buf := make([]byte, 2)
188
+		binary.BigEndian.PutUint16(buf, m.Header.Len)
189
+		return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, buf, "too long length")
190
+	}
191
+
192
+	return nil
193
+}
194
+
195
+func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) error {
196
+	if m.Version != 4 {
197
+		return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_VERSION_NUMBER, nil, fmt.Sprintf("upsuppored version %d", m.Version))
198
+	}
199
+
200
+	as := uint32(m.MyAS)
201
+	for _, p := range m.OptParams {
202
+		paramCap, y := p.(*OptionParameterCapability)
203
+		if !y {
204
+			continue
205
+		}
206
+		for _, c := range paramCap.Capability {
207
+			if c.Code() == BGP_CAP_FOUR_OCTET_AS_NUMBER {
208
+				cap := c.(*CapFourOctetASNumber)
209
+				as = cap.CapValue
210
+			}
211
+		}
212
+	}
213
+	if as != expectedAS {
214
+		return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_PEER_AS, nil, fmt.Sprintf("as number mismatch expected %d, received %d", expectedAS, as))
215
+	}
216
+
217
+	if m.HoldTime < 3 && m.HoldTime != 0 {
218
+		return NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNACCEPTABLE_HOLD_TIME, nil, fmt.Sprintf("unacceptable hold time %d", m.HoldTime))
219
+	}
220
+	return nil
221
+}

+ 102
- 0
vendor/golang.org/x/net/html/const.go Bestand weergeven

@@ -0,0 +1,102 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package html
6
+
7
+// Section 12.2.3.2 of the HTML5 specification says "The following elements
8
+// have varying levels of special parsing rules".
9
+// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
10
+var isSpecialElementMap = map[string]bool{
11
+	"address":    true,
12
+	"applet":     true,
13
+	"area":       true,
14
+	"article":    true,
15
+	"aside":      true,
16
+	"base":       true,
17
+	"basefont":   true,
18
+	"bgsound":    true,
19
+	"blockquote": true,
20
+	"body":       true,
21
+	"br":         true,
22
+	"button":     true,
23
+	"caption":    true,
24
+	"center":     true,
25
+	"col":        true,
26
+	"colgroup":   true,
27
+	"dd":         true,
28
+	"details":    true,
29
+	"dir":        true,
30
+	"div":        true,
31
+	"dl":         true,
32
+	"dt":         true,
33
+	"embed":      true,
34
+	"fieldset":   true,
35
+	"figcaption": true,
36
+	"figure":     true,
37
+	"footer":     true,
38
+	"form":       true,
39
+	"frame":      true,
40
+	"frameset":   true,
41
+	"h1":         true,
42
+	"h2":         true,
43
+	"h3":         true,
44
+	"h4":         true,
45
+	"h5":         true,
46
+	"h6":         true,
47
+	"head":       true,
48
+	"header":     true,
49
+	"hgroup":     true,
50
+	"hr":         true,
51
+	"html":       true,
52
+	"iframe":     true,
53
+	"img":        true,
54
+	"input":      true,
55
+	"isindex":    true,
56
+	"li":         true,
57
+	"link":       true,
58
+	"listing":    true,
59
+	"marquee":    true,
60
+	"menu":       true,
61
+	"meta":       true,
62
+	"nav":        true,
63
+	"noembed":    true,
64
+	"noframes":   true,
65
+	"noscript":   true,
66
+	"object":     true,
67
+	"ol":         true,
68
+	"p":          true,
69
+	"param":      true,
70
+	"plaintext":  true,
71
+	"pre":        true,
72
+	"script":     true,
73
+	"section":    true,
74
+	"select":     true,
75
+	"source":     true,
76
+	"style":      true,
77
+	"summary":    true,
78
+	"table":      true,
79
+	"tbody":      true,
80
+	"td":         true,
81
+	"template":   true,
82
+	"textarea":   true,
83
+	"tfoot":      true,
84
+	"th":         true,
85
+	"thead":      true,
86
+	"title":      true,
87
+	"tr":         true,
88
+	"track":      true,
89
+	"ul":         true,
90
+	"wbr":        true,
91
+	"xmp":        true,
92
+}
93
+
94
+func isSpecialElement(element *Node) bool {
95
+	switch element.Namespace {
96
+	case "", "html":
97
+		return isSpecialElementMap[element.Data]
98
+	case "svg":
99
+		return element.Data == "foreignObject"
100
+	}
101
+	return false
102
+}

+ 106
- 0
vendor/golang.org/x/net/html/doc.go Bestand weergeven

@@ -0,0 +1,106 @@
1
+// Copyright 2010 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+/*
6
+Package html implements an HTML5-compliant tokenizer and parser.
7
+
8
+Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
9
+caller's responsibility to ensure that r provides UTF-8 encoded HTML.
10
+
11
+	z := html.NewTokenizer(r)
12
+
13
+Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
14
+which parses the next token and returns its type, or an error:
15
+
16
+	for {
17
+		tt := z.Next()
18
+		if tt == html.ErrorToken {
19
+			// ...
20
+			return ...
21
+		}
22
+		// Process the current token.
23
+	}
24
+
25
+There are two APIs for retrieving the current token. The high-level API is to
26
+call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
27
+allow optionally calling Raw after Next but before Token, Text, TagName, or
28
+TagAttr. In EBNF notation, the valid call sequence per token is:
29
+
30
+	Next {Raw} [ Token | Text | TagName {TagAttr} ]
31
+
32
+Token returns an independent data structure that completely describes a token.
33
+Entities (such as "&lt;") are unescaped, tag names and attribute keys are
34
+lower-cased, and attributes are collected into a []Attribute. For example:
35
+
36
+	for {
37
+		if z.Next() == html.ErrorToken {
38
+			// Returning io.EOF indicates success.
39
+			return z.Err()
40
+		}
41
+		emitToken(z.Token())
42
+	}
43
+
44
+The low-level API performs fewer allocations and copies, but the contents of
45
+the []byte values returned by Text, TagName and TagAttr may change on the next
46
+call to Next. For example, to extract an HTML page's anchor text:
47
+
48
+	depth := 0
49
+	for {
50
+		tt := z.Next()
51
+		switch tt {
52
+		case ErrorToken:
53
+			return z.Err()
54
+		case TextToken:
55
+			if depth > 0 {
56
+				// emitBytes should copy the []byte it receives,
57
+				// if it doesn't process it immediately.
58
+				emitBytes(z.Text())
59
+			}
60
+		case StartTagToken, EndTagToken:
61
+			tn, _ := z.TagName()
62
+			if len(tn) == 1 && tn[0] == 'a' {
63
+				if tt == StartTagToken {
64
+					depth++
65
+				} else {
66
+					depth--
67
+				}
68
+			}
69
+		}
70
+	}
71
+
72
+Parsing is done by calling Parse with an io.Reader, which returns the root of
73
+the parse tree (the document element) as a *Node. It is the caller's
74
+responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
75
+example, to process each anchor node in depth-first order:
76
+
77
+	doc, err := html.Parse(r)
78
+	if err != nil {
79
+		// ...
80
+	}
81
+	var f func(*html.Node)
82
+	f = func(n *html.Node) {
83
+		if n.Type == html.ElementNode && n.Data == "a" {
84
+			// Do something with n...
85
+		}
86
+		for c := n.FirstChild; c != nil; c = c.NextSibling {
87
+			f(c)
88
+		}
89
+	}
90
+	f(doc)
91
+
92
+The relevant specifications include:
93
+https://html.spec.whatwg.org/multipage/syntax.html and
94
+https://html.spec.whatwg.org/multipage/syntax.html#tokenization
95
+*/
96
+package html // import "golang.org/x/net/html"
97
+
98
+// The tokenization algorithm implemented by this package is not a line-by-line
99
+// transliteration of the relatively verbose state-machine in the WHATWG
100
+// specification. A more direct approach is used instead, where the program
101
+// counter implies the state, such as whether it is tokenizing a tag or a text
102
+// node. Specification compliance is verified by checking expected and actual
103
+// outputs over a test suite rather than aiming for algorithmic fidelity.
104
+
105
+// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
106
+// TODO(nigeltao): How does parsing interact with a JavaScript engine?

+ 156
- 0
vendor/golang.org/x/net/html/doctype.go Bestand weergeven

@@ -0,0 +1,156 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package html
6
+
7
+import (
8
+	"strings"
9
+)
10
+
11
+// parseDoctype parses the data from a DoctypeToken into a name,
12
+// public identifier, and system identifier. It returns a Node whose Type
13
+// is DoctypeNode, whose Data is the name, and which has attributes
14
+// named "system" and "public" for the two identifiers if they were present.
15
+// quirks is whether the document should be parsed in "quirks mode".
16
+func parseDoctype(s string) (n *Node, quirks bool) {
17
+	n = &Node{Type: DoctypeNode}
18
+
19
+	// Find the name.
20
+	space := strings.IndexAny(s, whitespace)
21
+	if space == -1 {
22
+		space = len(s)
23
+	}
24
+	n.Data = s[:space]
25
+	// The comparison to "html" is case-sensitive.
26
+	if n.Data != "html" {
27
+		quirks = true
28
+	}
29
+	n.Data = strings.ToLower(n.Data)
30
+	s = strings.TrimLeft(s[space:], whitespace)
31
+
32
+	if len(s) < 6 {
33
+		// It can't start with "PUBLIC" or "SYSTEM".
34
+		// Ignore the rest of the string.
35
+		return n, quirks || s != ""
36
+	}
37
+
38
+	key := strings.ToLower(s[:6])
39
+	s = s[6:]
40
+	for key == "public" || key == "system" {
41
+		s = strings.TrimLeft(s, whitespace)
42
+		if s == "" {
43
+			break
44
+		}
45
+		quote := s[0]
46
+		if quote != '"' && quote != '\'' {
47
+			break
48
+		}
49
+		s = s[1:]
50
+		q := strings.IndexRune(s, rune(quote))
51
+		var id string
52
+		if q == -1 {
53
+			id = s
54
+			s = ""
55
+		} else {
56
+			id = s[:q]
57
+			s = s[q+1:]
58
+		}
59
+		n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
60
+		if key == "public" {
61
+			key = "system"
62
+		} else {
63
+			key = ""
64
+		}
65
+	}
66
+
67
+	if key != "" || s != "" {
68
+		quirks = true
69
+	} else if len(n.Attr) > 0 {
70
+		if n.Attr[0].Key == "public" {
71
+			public := strings.ToLower(n.Attr[0].Val)
72
+			switch public {
73
+			case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
74
+				quirks = true
75
+			default:
76
+				for _, q := range quirkyIDs {
77
+					if strings.HasPrefix(public, q) {
78
+						quirks = true
79
+						break
80
+					}
81
+				}
82
+			}
83
+			// The following two public IDs only cause quirks mode if there is no system ID.
84
+			if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
85
+				strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
86
+				quirks = true
87
+			}
88
+		}
89
+		if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
90
+			strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
91
+			quirks = true
92
+		}
93
+	}
94
+
95
+	return n, quirks
96
+}
97
+
98
+// quirkyIDs is a list of public doctype identifiers that cause a document
99
+// to be interpreted in quirks mode. The identifiers should be in lower case.
100
+var quirkyIDs = []string{
101
+	"+//silmaril//dtd html pro v0r11 19970101//",
102
+	"-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
103
+	"-//as//dtd html 3.0 aswedit + extensions//",
104
+	"-//ietf//dtd html 2.0 level 1//",
105
+	"-//ietf//dtd html 2.0 level 2//",
106
+	"-//ietf//dtd html 2.0 strict level 1//",
107
+	"-//ietf//dtd html 2.0 strict level 2//",
108
+	"-//ietf//dtd html 2.0 strict//",
109
+	"-//ietf//dtd html 2.0//",
110
+	"-//ietf//dtd html 2.1e//",
111
+	"-//ietf//dtd html 3.0//",
112
+	"-//ietf//dtd html 3.2 final//",
113
+	"-//ietf//dtd html 3.2//",
114
+	"-//ietf//dtd html 3//",
115
+	"-//ietf//dtd html level 0//",
116
+	"-//ietf//dtd html level 1//",
117
+	"-//ietf//dtd html level 2//",
118
+	"-//ietf//dtd html level 3//",
119
+	"-//ietf//dtd html strict level 0//",
120
+	"-//ietf//dtd html strict level 1//",
121
+	"-//ietf//dtd html strict level 2//",
122
+	"-//ietf//dtd html strict level 3//",
123
+	"-//ietf//dtd html strict//",
124
+	"-//ietf//dtd html//",
125
+	"-//metrius//dtd metrius presentational//",
126
+	"-//microsoft//dtd internet explorer 2.0 html strict//",
127
+	"-//microsoft//dtd internet explorer 2.0 html//",
128
+	"-//microsoft//dtd internet explorer 2.0 tables//",
129
+	"-//microsoft//dtd internet explorer 3.0 html strict//",
130
+	"-//microsoft//dtd internet explorer 3.0 html//",
131
+	"-//microsoft//dtd internet explorer 3.0 tables//",
132
+	"-//netscape comm. corp.//dtd html//",
133
+	"-//netscape comm. corp.//dtd strict html//",
134
+	"-//o'reilly and associates//dtd html 2.0//",
135
+	"-//o'reilly and associates//dtd html extended 1.0//",
136
+	"-//o'reilly and associates//dtd html extended relaxed 1.0//",
137
+	"-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
138
+	"-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
139
+	"-//spyglass//dtd html 2.0 extended//",
140
+	"-//sq//dtd html 2.0 hotmetal + extensions//",
141
+	"-//sun microsystems corp.//dtd hotjava html//",
142
+	"-//sun microsystems corp.//dtd hotjava strict html//",
143
+	"-//w3c//dtd html 3 1995-03-24//",
144
+	"-//w3c//dtd html 3.2 draft//",
145
+	"-//w3c//dtd html 3.2 final//",
146
+	"-//w3c//dtd html 3.2//",
147
+	"-//w3c//dtd html 3.2s draft//",
148
+	"-//w3c//dtd html 4.0 frameset//",
149
+	"-//w3c//dtd html 4.0 transitional//",
150
+	"-//w3c//dtd html experimental 19960712//",
151
+	"-//w3c//dtd html experimental 970421//",
152
+	"-//w3c//dtd w3 html//",
153
+	"-//w3o//dtd w3 html 3.0//",
154
+	"-//webtechs//dtd mozilla html 2.0//",
155
+	"-//webtechs//dtd mozilla html//",
156
+}

+ 2253
- 0
vendor/golang.org/x/net/html/entity.go
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 258
- 0
vendor/golang.org/x/net/html/escape.go Bestand weergeven

@@ -0,0 +1,258 @@
1
+// Copyright 2010 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package html
6
+
7
+import (
8
+	"bytes"
9
+	"strings"
10
+	"unicode/utf8"
11
+)
12
+
13
+// These replacements permit compatibility with old numeric entities that
14
+// assumed Windows-1252 encoding.
15
+// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
16
+var replacementTable = [...]rune{
17
+	'\u20AC', // First entry is what 0x80 should be replaced with.
18
+	'\u0081',
19
+	'\u201A',
20
+	'\u0192',
21
+	'\u201E',
22
+	'\u2026',
23
+	'\u2020',
24
+	'\u2021',
25
+	'\u02C6',
26
+	'\u2030',
27
+	'\u0160',
28
+	'\u2039',
29
+	'\u0152',
30
+	'\u008D',
31
+	'\u017D',
32
+	'\u008F',
33
+	'\u0090',
34
+	'\u2018',
35
+	'\u2019',
36
+	'\u201C',
37
+	'\u201D',
38
+	'\u2022',
39
+	'\u2013',
40
+	'\u2014',
41
+	'\u02DC',
42
+	'\u2122',
43
+	'\u0161',
44
+	'\u203A',
45
+	'\u0153',
46
+	'\u009D',
47
+	'\u017E',
48
+	'\u0178', // Last entry is 0x9F.
49
+	// 0x00->'\uFFFD' is handled programmatically.
50
+	// 0x0D->'\u000D' is a no-op.
51
+}
52
+
53
+// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
54
+// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
55
+// Precondition: b[src] == '&' && dst <= src.
56
+// attribute should be true if parsing an attribute value.
57
+func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
58
+	// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
59
+
60
+	// i starts at 1 because we already know that s[0] == '&'.
61
+	i, s := 1, b[src:]
62
+
63
+	if len(s) <= 1 {
64
+		b[dst] = b[src]
65
+		return dst + 1, src + 1
66
+	}
67
+
68
+	if s[i] == '#' {
69
+		if len(s) <= 3 { // We need to have at least "&#.".
70
+			b[dst] = b[src]
71
+			return dst + 1, src + 1
72
+		}
73
+		i++
74
+		c := s[i]
75
+		hex := false
76
+		if c == 'x' || c == 'X' {
77
+			hex = true
78
+			i++
79
+		}
80
+
81
+		x := '\x00'
82
+		for i < len(s) {
83
+			c = s[i]
84
+			i++
85
+			if hex {
86
+				if '0' <= c && c <= '9' {
87
+					x = 16*x + rune(c) - '0'
88
+					continue
89
+				} else if 'a' <= c && c <= 'f' {
90
+					x = 16*x + rune(c) - 'a' + 10
91
+					continue
92
+				} else if 'A' <= c && c <= 'F' {
93
+					x = 16*x + rune(c) - 'A' + 10
94
+					continue
95
+				}
96
+			} else if '0' <= c && c <= '9' {
97
+				x = 10*x + rune(c) - '0'
98
+				continue
99
+			}
100
+			if c != ';' {
101
+				i--
102
+			}
103
+			break
104
+		}
105
+
106
+		if i <= 3 { // No characters matched.
107
+			b[dst] = b[src]
108
+			return dst + 1, src + 1
109
+		}
110
+
111
+		if 0x80 <= x && x <= 0x9F {
112
+			// Replace characters from Windows-1252 with UTF-8 equivalents.
113
+			x = replacementTable[x-0x80]
114
+		} else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
115
+			// Replace invalid characters with the replacement character.
116
+			x = '\uFFFD'
117
+		}
118
+
119
+		return dst + utf8.EncodeRune(b[dst:], x), src + i
120
+	}
121
+
122
+	// Consume the maximum number of characters possible, with the
123
+	// consumed characters matching one of the named references.
124
+
125
+	for i < len(s) {
126
+		c := s[i]
127
+		i++
128
+		// Lower-cased characters are more common in entities, so we check for them first.
129
+		if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
130
+			continue
131
+		}
132
+		if c != ';' {
133
+			i--
134
+		}
135
+		break
136
+	}
137
+
138
+	entityName := string(s[1:i])
139
+	if entityName == "" {
140
+		// No-op.
141
+	} else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
142
+		// No-op.
143
+	} else if x := entity[entityName]; x != 0 {
144
+		return dst + utf8.EncodeRune(b[dst:], x), src + i
145
+	} else if x := entity2[entityName]; x[0] != 0 {
146
+		dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
147
+		return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
148
+	} else if !attribute {
149
+		maxLen := len(entityName) - 1
150
+		if maxLen > longestEntityWithoutSemicolon {
151
+			maxLen = longestEntityWithoutSemicolon
152
+		}
153
+		for j := maxLen; j > 1; j-- {
154
+			if x := entity[entityName[:j]]; x != 0 {
155
+				return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
156
+			}
157
+		}
158
+	}
159
+
160
+	dst1, src1 = dst+i, src+i
161
+	copy(b[dst:dst1], b[src:src1])
162
+	return dst1, src1
163
+}
164
+
165
+// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
166
+// attribute should be true if parsing an attribute value.
167
+func unescape(b []byte, attribute bool) []byte {
168
+	for i, c := range b {
169
+		if c == '&' {
170
+			dst, src := unescapeEntity(b, i, i, attribute)
171
+			for src < len(b) {
172
+				c := b[src]
173
+				if c == '&' {
174
+					dst, src = unescapeEntity(b, dst, src, attribute)
175
+				} else {
176
+					b[dst] = c
177
+					dst, src = dst+1, src+1
178
+				}
179
+			}
180
+			return b[0:dst]
181
+		}
182
+	}
183
+	return b
184
+}
185
+
186
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
187
+func lower(b []byte) []byte {
188
+	for i, c := range b {
189
+		if 'A' <= c && c <= 'Z' {
190
+			b[i] = c + 'a' - 'A'
191
+		}
192
+	}
193
+	return b
194
+}
195
+
196
+const escapedChars = "&'<>\"\r"
197
+
198
+func escape(w writer, s string) error {
199
+	i := strings.IndexAny(s, escapedChars)
200
+	for i != -1 {
201
+		if _, err := w.WriteString(s[:i]); err != nil {
202
+			return err
203
+		}
204
+		var esc string
205
+		switch s[i] {
206
+		case '&':
207
+			esc = "&amp;"
208
+		case '\'':
209
+			// "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
210
+			esc = "&#39;"
211
+		case '<':
212
+			esc = "&lt;"
213
+		case '>':
214
+			esc = "&gt;"
215
+		case '"':
216
+			// "&#34;" is shorter than "&quot;".
217
+			esc = "&#34;"
218
+		case '\r':
219
+			esc = "&#13;"
220
+		default:
221
+			panic("unrecognized escape character")
222
+		}
223
+		s = s[i+1:]
224
+		if _, err := w.WriteString(esc); err != nil {
225
+			return err
226
+		}
227
+		i = strings.IndexAny(s, escapedChars)
228
+	}
229
+	_, err := w.WriteString(s)
230
+	return err
231
+}
232
+
233
+// EscapeString escapes special characters like "<" to become "&lt;". It
234
+// escapes only five such characters: <, >, &, ' and ".
235
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
236
+// always true.
237
+func EscapeString(s string) string {
238
+	if strings.IndexAny(s, escapedChars) == -1 {
239
+		return s
240
+	}
241
+	var buf bytes.Buffer
242
+	escape(&buf, s)
243
+	return buf.String()
244
+}
245
+
246
+// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
247
+// larger range of entities than EscapeString escapes. For example, "&aacute;"
248
+// unescapes to "á", as does "&#225;" and "&xE1;".
249
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
250
+// always true.
251
+func UnescapeString(s string) string {
252
+	for _, c := range s {
253
+		if c == '&' {
254
+			return string(unescape([]byte(s), false))
255
+		}
256
+	}
257
+	return s
258
+}

+ 226
- 0
vendor/golang.org/x/net/html/foreign.go Bestand weergeven

@@ -0,0 +1,226 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package html
6
+
7
+import (
8
+	"strings"
9
+)
10
+
11
+func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
12
+	for i := range aa {
13
+		if newName, ok := nameMap[aa[i].Key]; ok {
14
+			aa[i].Key = newName
15
+		}
16
+	}
17
+}
18
+
19
+func adjustForeignAttributes(aa []Attribute) {
20
+	for i, a := range aa {
21
+		if a.Key == "" || a.Key[0] != 'x' {
22
+			continue
23
+		}
24
+		switch a.Key {
25
+		case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
26
+			"xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
27
+			j := strings.Index(a.Key, ":")
28
+			aa[i].Namespace = a.Key[:j]
29
+			aa[i].Key = a.Key[j+1:]
30
+		}
31
+	}
32
+}
33
+
34
+func htmlIntegrationPoint(n *Node) bool {
35
+	if n.Type != ElementNode {
36
+		return false
37
+	}
38
+	switch n.Namespace {
39
+	case "math":
40
+		if n.Data == "annotation-xml" {
41
+			for _, a := range n.Attr {
42
+				if a.Key == "encoding" {
43
+					val := strings.ToLower(a.Val)
44
+					if val == "text/html" || val == "application/xhtml+xml" {
45
+						return true
46
+					}
47
+				}
48
+			}
49
+		}
50
+	case "svg":
51
+		switch n.Data {
52
+		case "desc", "foreignObject", "title":
53
+			return true
54
+		}
55
+	}
56
+	return false
57
+}
58
+
59
+func mathMLTextIntegrationPoint(n *Node) bool {
60
+	if n.Namespace != "math" {
61
+		return false
62
+	}
63
+	switch n.Data {
64
+	case "mi", "mo", "mn", "ms", "mtext":
65
+		return true
66
+	}
67
+	return false
68
+}
69
+
70
+// Section 12.2.5.5.
71
+var breakout = map[string]bool{
72
+	"b":          true,
73
+	"big":        true,
74
+	"blockquote": true,
75
+	"body":       true,
76
+	"br":         true,
77
+	"center":     true,
78
+	"code":       true,
79
+	"dd":         true,
80
+	"div":        true,
81
+	"dl":         true,
82
+	"dt":         true,
83
+	"em":         true,
84
+	"embed":      true,
85
+	"h1":         true,
86
+	"h2":         true,
87
+	"h3":         true,
88
+	"h4":         true,
89
+	"h5":         true,
90
+	"h6":         true,
91
+	"head":       true,
92
+	"hr":         true,
93
+	"i":          true,
94
+	"img":        true,
95
+	"li":         true,
96
+	"listing":    true,
97
+	"menu":       true,
98
+	"meta":       true,
99
+	"nobr":       true,
100
+	"ol":         true,
101
+	"p":          true,
102
+	"pre":        true,
103
+	"ruby":       true,
104
+	"s":          true,
105
+	"small":      true,
106
+	"span":       true,
107
+	"strong":     true,
108
+	"strike":     true,
109
+	"sub":        true,
110
+	"sup":        true,
111
+	"table":      true,
112
+	"tt":         true,
113
+	"u":          true,
114
+	"ul":         true,
115
+	"var":        true,
116
+}
117
+
118
+// Section 12.2.5.5.
119
+var svgTagNameAdjustments = map[string]string{
120
+	"altglyph":            "altGlyph",
121
+	"altglyphdef":         "altGlyphDef",
122
+	"altglyphitem":        "altGlyphItem",
123
+	"animatecolor":        "animateColor",
124
+	"animatemotion":       "animateMotion",
125
+	"animatetransform":    "animateTransform",
126
+	"clippath":            "clipPath",
127
+	"feblend":             "feBlend",
128
+	"fecolormatrix":       "feColorMatrix",
129
+	"fecomponenttransfer": "feComponentTransfer",
130
+	"fecomposite":         "feComposite",
131
+	"feconvolvematrix":    "feConvolveMatrix",
132
+	"fediffuselighting":   "feDiffuseLighting",
133
+	"fedisplacementmap":   "feDisplacementMap",
134
+	"fedistantlight":      "feDistantLight",
135
+	"feflood":             "feFlood",
136
+	"fefunca":             "feFuncA",
137
+	"fefuncb":             "feFuncB",
138
+	"fefuncg":             "feFuncG",
139
+	"fefuncr":             "feFuncR",
140
+	"fegaussianblur":      "feGaussianBlur",
141
+	"feimage":             "feImage",
142
+	"femerge":             "feMerge",
143
+	"femergenode":         "feMergeNode",
144
+	"femorphology":        "feMorphology",
145
+	"feoffset":            "feOffset",
146
+	"fepointlight":        "fePointLight",
147
+	"fespecularlighting":  "feSpecularLighting",
148
+	"fespotlight":         "feSpotLight",
149
+	"fetile":              "feTile",
150
+	"feturbulence":        "feTurbulence",
151
+	"foreignobject":       "foreignObject",
152
+	"glyphref":            "glyphRef",
153
+	"lineargradient":      "linearGradient",
154
+	"radialgradient":      "radialGradient",
155
+	"textpath":            "textPath",
156
+}
157
+
158
+// Section 12.2.5.1
159
+var mathMLAttributeAdjustments = map[string]string{
160
+	"definitionurl": "definitionURL",
161
+}
162
+
163
+var svgAttributeAdjustments = map[string]string{
164
+	"attributename":             "attributeName",
165
+	"attributetype":             "attributeType",
166
+	"basefrequency":             "baseFrequency",
167
+	"baseprofile":               "baseProfile",
168
+	"calcmode":                  "calcMode",
169
+	"clippathunits":             "clipPathUnits",
170
+	"contentscripttype":         "contentScriptType",
171
+	"contentstyletype":          "contentStyleType",
172
+	"diffuseconstant":           "diffuseConstant",
173
+	"edgemode":                  "edgeMode",
174
+	"externalresourcesrequired": "externalResourcesRequired",
175
+	"filterres":                 "filterRes",
176
+	"filterunits":               "filterUnits",
177
+	"glyphref":                  "glyphRef",
178
+	"gradienttransform":         "gradientTransform",
179
+	"gradientunits":             "gradientUnits",
180
+	"kernelmatrix":              "kernelMatrix",
181
+	"kernelunitlength":          "kernelUnitLength",
182
+	"keypoints":                 "keyPoints",
183
+	"keysplines":                "keySplines",
184
+	"keytimes":                  "keyTimes",
185
+	"lengthadjust":              "lengthAdjust",
186
+	"limitingconeangle":         "limitingConeAngle",
187
+	"markerheight":              "markerHeight",
188
+	"markerunits":               "markerUnits",
189
+	"markerwidth":               "markerWidth",
190
+	"maskcontentunits":          "maskContentUnits",
191
+	"maskunits":                 "maskUnits",
192
+	"numoctaves":                "numOctaves",
193
+	"pathlength":                "pathLength",
194
+	"patterncontentunits":       "patternContentUnits",
195
+	"patterntransform":          "patternTransform",
196
+	"patternunits":              "patternUnits",
197
+	"pointsatx":                 "pointsAtX",
198
+	"pointsaty":                 "pointsAtY",
199
+	"pointsatz":                 "pointsAtZ",
200
+	"preservealpha":             "preserveAlpha",
201
+	"preserveaspectratio":       "preserveAspectRatio",
202
+	"primitiveunits":            "primitiveUnits",
203
+	"refx":                      "refX",
204
+	"refy":                      "refY",
205
+	"repeatcount":               "repeatCount",
206
+	"repeatdur":                 "repeatDur",
207
+	"requiredextensions":        "requiredExtensions",
208
+	"requiredfeatures":          "requiredFeatures",
209
+	"specularconstant":          "specularConstant",
210
+	"specularexponent":          "specularExponent",
211
+	"spreadmethod":              "spreadMethod",
212
+	"startoffset":               "startOffset",
213
+	"stddeviation":              "stdDeviation",
214
+	"stitchtiles":               "stitchTiles",
215
+	"surfacescale":              "surfaceScale",
216
+	"systemlanguage":            "systemLanguage",
217
+	"tablevalues":               "tableValues",
218
+	"targetx":                   "targetX",
219
+	"targety":                   "targetY",
220
+	"textlength":                "textLength",
221
+	"viewbox":                   "viewBox",
222
+	"viewtarget":                "viewTarget",
223
+	"xchannelselector":          "xChannelSelector",
224
+	"ychannelselector":          "yChannelSelector",
225
+	"zoomandpan":                "zoomAndPan",
226
+}

+ 193
- 0
vendor/golang.org/x/net/html/node.go Bestand weergeven

@@ -0,0 +1,193 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package html
6
+
7
+import (
8
+	"golang.org/x/net/html/atom"
9
+)
10
+
11
+// A NodeType is the type of a Node.
12
+type NodeType uint32
13
+
14
+const (
15
+	ErrorNode NodeType = iota
16
+	TextNode
17
+	DocumentNode
18
+	ElementNode
19
+	CommentNode
20
+	DoctypeNode
21
+	scopeMarkerNode
22
+)
23
+
24
+// Section 12.2.3.3 says "scope markers are inserted when entering applet
25
+// elements, buttons, object elements, marquees, table cells, and table
26
+// captions, and are used to prevent formatting from 'leaking'".
27
+var scopeMarker = Node{Type: scopeMarkerNode}
28
+
29
+// A Node consists of a NodeType and some Data (tag name for element nodes,
30
+// content for text) and are part of a tree of Nodes. Element nodes may also
31
+// have a Namespace and contain a slice of Attributes. Data is unescaped, so
32
+// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
33
+// is the atom for Data, or zero if Data is not a known tag name.
34
+//
35
+// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
36
+// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
37
+// "svg" is short for "http://www.w3.org/2000/svg".
38
+type Node struct {
39
+	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
40
+
41
+	Type      NodeType
42
+	DataAtom  atom.Atom
43
+	Data      string
44
+	Namespace string
45
+	Attr      []Attribute
46
+}
47
+
48
+// InsertBefore inserts newChild as a child of n, immediately before oldChild
49
+// in the sequence of n's children. oldChild may be nil, in which case newChild
50
+// is appended to the end of n's children.
51
+//
52
+// It will panic if newChild already has a parent or siblings.
53
+func (n *Node) InsertBefore(newChild, oldChild *Node) {
54
+	if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
55
+		panic("html: InsertBefore called for an attached child Node")
56
+	}
57
+	var prev, next *Node
58
+	if oldChild != nil {
59
+		prev, next = oldChild.PrevSibling, oldChild
60
+	} else {
61
+		prev = n.LastChild
62
+	}
63
+	if prev != nil {
64
+		prev.NextSibling = newChild
65
+	} else {
66
+		n.FirstChild = newChild
67
+	}
68
+	if next != nil {
69
+		next.PrevSibling = newChild
70
+	} else {
71
+		n.LastChild = newChild
72
+	}
73
+	newChild.Parent = n
74
+	newChild.PrevSibling = prev
75
+	newChild.NextSibling = next
76
+}
77
+
78
+// AppendChild adds a node c as a child of n.
79
+//
80
+// It will panic if c already has a parent or siblings.
81
+func (n *Node) AppendChild(c *Node) {
82
+	if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
83
+		panic("html: AppendChild called for an attached child Node")
84
+	}
85
+	last := n.LastChild
86
+	if last != nil {
87
+		last.NextSibling = c
88
+	} else {
89
+		n.FirstChild = c
90
+	}
91
+	n.LastChild = c
92
+	c.Parent = n
93
+	c.PrevSibling = last
94
+}
95
+
96
+// RemoveChild removes a node c that is a child of n. Afterwards, c will have
97
+// no parent and no siblings.
98
+//
99
+// It will panic if c's parent is not n.
100
+func (n *Node) RemoveChild(c *Node) {
101
+	if c.Parent != n {
102
+		panic("html: RemoveChild called for a non-child Node")
103
+	}
104
+	if n.FirstChild == c {
105
+		n.FirstChild = c.NextSibling
106
+	}
107
+	if c.NextSibling != nil {
108
+		c.NextSibling.PrevSibling = c.PrevSibling
109
+	}
110
+	if n.LastChild == c {
111
+		n.LastChild = c.PrevSibling
112
+	}
113
+	if c.PrevSibling != nil {
114
+		c.PrevSibling.NextSibling = c.NextSibling
115
+	}
116
+	c.Parent = nil
117
+	c.PrevSibling = nil
118
+	c.NextSibling = nil
119
+}
120
+
121
+// reparentChildren reparents all of src's child nodes to dst.
122
+func reparentChildren(dst, src *Node) {
123
+	for {
124
+		child := src.FirstChild
125
+		if child == nil {
126
+			break
127
+		}
128
+		src.RemoveChild(child)
129
+		dst.AppendChild(child)
130
+	}
131
+}
132
+
133
+// clone returns a new node with the same type, data and attributes.
134
+// The clone has no parent, no siblings and no children.
135
+func (n *Node) clone() *Node {
136
+	m := &Node{
137
+		Type:     n.Type,
138
+		DataAtom: n.DataAtom,
139
+		Data:     n.Data,
140
+		Attr:     make([]Attribute, len(n.Attr)),
141
+	}
142
+	copy(m.Attr, n.Attr)
143
+	return m
144
+}
145
+
146
+// nodeStack is a stack of nodes.
147
+type nodeStack []*Node
148
+
149
+// pop pops the stack. It will panic if s is empty.
150
+func (s *nodeStack) pop() *Node {
151
+	i := len(*s)
152
+	n := (*s)[i-1]
153
+	*s = (*s)[:i-1]
154
+	return n
155
+}
156
+
157
+// top returns the most recently pushed node, or nil if s is empty.
158
+func (s *nodeStack) top() *Node {
159
+	if i := len(*s); i > 0 {
160
+		return (*s)[i-1]
161
+	}
162
+	return nil
163
+}
164
+
165
+// index returns the index of the top-most occurrence of n in the stack, or -1
166
+// if n is not present.
167
+func (s *nodeStack) index(n *Node) int {
168
+	for i := len(*s) - 1; i >= 0; i-- {
169
+		if (*s)[i] == n {
170
+			return i
171
+		}
172
+	}
173
+	return -1
174
+}
175
+
176
+// insert inserts a node at the given index.
177
+func (s *nodeStack) insert(i int, n *Node) {
178
+	(*s) = append(*s, nil)
179
+	copy((*s)[i+1:], (*s)[i:])
180
+	(*s)[i] = n
181
+}
182
+
183
+// remove removes a node from the stack. It is a no-op if n is not present.
184
+func (s *nodeStack) remove(n *Node) {
185
+	i := s.index(n)
186
+	if i == -1 {
187
+		return
188
+	}
189
+	copy((*s)[i:], (*s)[i+1:])
190
+	j := len(*s) - 1
191
+	(*s)[j] = nil
192
+	*s = (*s)[:j]
193
+}

+ 2094
- 0
vendor/golang.org/x/net/html/parse.go
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 271
- 0
vendor/golang.org/x/net/html/render.go Bestand weergeven

@@ -0,0 +1,271 @@
1
+// Copyright 2011 The Go Authors. All rights reserved.
2
+// Use of this source code is governed by a BSD-style
3
+// license that can be found in the LICENSE file.
4
+
5
+package html
6
+
7
+import (
8
+	"bufio"
9
+	"errors"
10
+	"fmt"
11
+	"io"
12
+	"strings"
13
+)
14
+
15
+type writer interface {
16
+	io.Writer
17
+	io.ByteWriter
18
+	WriteString(string) (int, error)
19
+}
20
+
21
+// Render renders the parse tree n to the given writer.
22
+//
23
+// Rendering is done on a 'best effort' basis: calling Parse on the output of
24
+// Render will always result in something similar to the original tree, but it
25
+// is not necessarily an exact clone unless the original tree was 'well-formed'.
26
+// 'Well-formed' is not easily specified; the HTML5 specification is
27
+// complicated.
28
+//
29
+// Calling Parse on arbitrary input typically results in a 'well-formed' parse
30
+// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
31
+// For example, in a 'well-formed' parse tree, no <a> element is a child of
32
+// another <a> element: parsing "<a><a>" results in two sibling elements.
33
+// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
34
+// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
35
+// children; the <a> is reparented to the <table>'s parent. However, calling
36
+// Parse on "<a><table><a>" does not return an error, but the result has an <a>
37
+// element with an <a> child, and is therefore not 'well-formed'.
38
+//
39
+// Programmatically constructed trees are typically also 'well-formed', but it
40
+// is possible to construct a tree that looks innocuous but, when rendered and
41
+// re-parsed, results in a different tree. A simple example is that a solitary
42
+// text node would become a tree containing <html>, <head> and <body> elements.
43
+// Another example is that the programmatic equivalent of "a<head>b</head>c"
44
+// becomes "<html><head><head/><body>abc</body></html>".
45
+func Render(w io.Writer, n *Node) error {
46
+	if x, ok := w.(writer); ok {
47
+		return render(x, n)
48
+	}
49
+	buf := bufio.NewWriter(w)
50
+	if err := render(buf, n); err != nil {
51
+		return err
52
+	}
53
+	return buf.Flush()
54
+}
55
+
56
+// plaintextAbort is returned from render1 when a <plaintext> element
57
+// has been rendered. No more end tags should be rendered after that.
58
+var plaintextAbort = errors.New("html: internal error (plaintext abort)")
59
+
60
+func render(w writer, n *Node) error {
61
+	err := render1(w, n)
62
+	if err == plaintextAbort {
63
+		err = nil
64
+	}
65
+	return err
66
+}
67
+
68
+func render1(w writer, n *Node) error {
69
+	// Render non-element nodes; these are the easy cases.
70
+	switch n.Type {
71
+	case ErrorNode:
72
+		return errors.New("html: cannot render an ErrorNode node")
73
+	case TextNode:
74
+		return escape(w, n.Data)
75
+	case DocumentNode:
76
+		for c := n.FirstChild; c != nil; c = c.NextSibling {
77
+			if err := render1(w, c); err != nil {
78
+				return err
79
+			}
80
+		}
81
+		return nil
82
+	case ElementNode:
83
+		// No-op.
84
+	case CommentNode:
85
+		if _, err := w.WriteString("<!--"); err != nil {
86
+			return err
87
+		}
88
+		if _, err := w.WriteString(n.Data); err != nil {
89
+			return err
90
+		}
91
+		if _, err := w.WriteString("-->"); err != nil {
92
+			return err
93
+		}
94
+		return nil
95
+	case DoctypeNode:
96
+		if _, err := w.WriteString("<!DOCTYPE "); err != nil {
97
+			return err
98
+		}
99
+		if _, err := w.WriteString(n.Data); err != nil {
100
+			return err
101
+		}
102
+		if n.Attr != nil {
103
+			var p, s string
104
+			for _, a := range n.Attr {
105
+				switch a.Key {
106
+				case "public":
107
+					p = a.Val
108
+				case "system":
109
+					s = a.Val
110
+				}
111
+			}
112
+			if p != "" {
113
+				if _, err := w.WriteString(" PUBLIC "); err != nil {
114
+					return err
115
+				}
116
+				if err := writeQuoted(w, p); err != nil {
117
+					return err
118
+				}
119
+				if s != "" {
120
+					if err := w.WriteByte(' '); err != nil {
121
+						return err
122
+					}
123
+					if err := writeQuoted(w, s); err != nil {
124
+						return err
125
+					}
126
+				}
127
+			} else if s != "" {
128
+				if _, err := w.WriteString(" SYSTEM "); err != nil {
129
+					return err
130
+				}
131
+				if err := writeQuoted(w, s); err != nil {
132
+					return err
133
+				}
134
+			}
135
+		}
136
+		return w.WriteByte('>')
137
+	default:
138
+		return errors.New("html: unknown node type")
139
+	}
140
+
141
+	// Render the <xxx> opening tag.
142
+	if err := w.WriteByte('<'); err != nil {
143
+		return err
144
+	}
145
+	if _, err := w.WriteString(n.Data); err != nil {
146
+		return err
147
+	}
148
+	for _, a := range n.Attr {
149
+		if err := w.WriteByte(' '); err != nil {
150
+			return err
151
+		}
152
+		if a.Namespace != "" {
153
+			if _, err := w.WriteString(a.Namespace); err != nil {
154
+				return err
155
+			}
156
+			if err := w.WriteByte(':'); err != nil {
157
+				return err
158
+			}
159
+		}
160
+		if _, err := w.WriteString(a.Key); err != nil {
161
+			return err
162
+		}
163
+		if _, err := w.WriteString(`="`); err != nil {
164
+			return err
165
+		}
166
+		if err := escape(w, a.Val); err != nil {
167
+			return err
168
+		}
169
+		if err := w.WriteByte('"'); err != nil {
170
+			return err
171
+		}
172
+	}
173
+	if voidElements[n.Data] {
174
+		if n.FirstChild != nil {
175
+			return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
176
+		}
177
+		_, err := w.WriteString("/>")
178
+		return err
179
+	}
180
+	if err := w.WriteByte('>'); err != nil {
181
+		return err
182
+	}
183
+
184
+	// Add initial newline where there is danger of a newline beging ignored.
185
+	if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
186
+		switch n.Data {
187
+		case "pre", "listing", "textarea":
188
+			if err := w.WriteByte('\n'); err != nil {
189
+				return err
190
+			}
191
+		}
192
+	}
193
+
194
+	// Render any child nodes.
195
+	switch n.Data {
196
+	case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
197
+		for c := n.FirstChild; c != nil; c = c.NextSibling {
198
+			if c.Type == TextNode {
199
+				if _, err := w.WriteString(c.Data); err != nil {
200
+					return err
201
+				}
202
+			} else {
203
+				if err := render1(w, c); err != nil {
204
+					return err
205
+				}
206
+			}
207
+		}
208
+		if n.Data == "plaintext" {
209
+			// Don't render anything else. <plaintext> must be the
210
+			// last element in the file, with no closing tag.
211
+			return plaintextAbort
212
+		}
213
+	default:
214
+		for c := n.FirstChild; c != nil; c = c.NextSibling {
215
+			if err := render1(w, c); err != nil {
216
+				return err
217
+			}
218
+		}
219
+	}
220
+
221
+	// Render the </xxx> closing tag.
222
+	if _, err := w.WriteString("</"); err != nil {
223
+		return err
224
+	}
225
+	if _, err := w.WriteString(n.Data); err != nil {
226
+		return err
227
+	}
228
+	return w.WriteByte('>')
229
+}
230
+
231
+// writeQuoted writes s to w surrounded by quotes. Normally it will use double
232
+// quotes, but if s contains a double quote, it will use single quotes.
233
+// It is used for writing the identifiers in a doctype declaration.
234
+// In valid HTML, they can't contain both types of quotes.
235
+func writeQuoted(w writer, s string) error {
236
+	var q byte = '"'
237
+	if strings.Contains(s, `"`) {
238
+		q = '\''
239
+	}
240
+	if err := w.WriteByte(q); err != nil {
241
+		return err
242
+	}
243
+	if _, err := w.WriteString(s); err != nil {
244
+		return err
245
+	}
246
+	if err := w.WriteByte(q); err != nil {
247
+		return err
248
+	}
249
+	return nil
250
+}
251
+
252
+// Section 12.1.2, "Elements", gives this list of void elements. Void elements
253
+// are those that can't have any contents.
254
+var voidElements = map[string]bool{
255
+	"area":    true,
256
+	"base":    true,
257
+	"br":      true,
258
+	"col":     true,
259
+	"command": true,
260
+	"embed":   true,
261
+	"hr":      true,
262
+	"img":     true,
263
+	"input":   true,
264
+	"keygen":  true,
265
+	"link":    true,
266
+	"meta":    true,
267
+	"param":   true,
268
+	"source":  true,
269
+	"track":   true,
270
+	"wbr":     true,
271
+}

+ 1219
- 0
vendor/golang.org/x/net/html/token.go
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 31
- 0
vendor/vendor.json Bestand weergeven

@@ -0,0 +1,31 @@
1
+{
2
+	"comment": "",
3
+	"ignore": "test",
4
+	"package": [
5
+		{
6
+			"path": "github.com/davecgh/go-spew/spew",
7
+			"revision": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d",
8
+			"revisionTime": "2015-11-05T15:09:06-06:00"
9
+		},
10
+		{
11
+			"path": "github.com/garyburd/redigo/internal",
12
+			"revision": "836b6e58b3358112c8291565d01c35b8764070d7",
13
+			"revisionTime": "2015-12-19T15:20:44-08:00"
14
+		},
15
+		{
16
+			"path": "github.com/garyburd/redigo/redis",
17
+			"revision": "836b6e58b3358112c8291565d01c35b8764070d7",
18
+			"revisionTime": "2015-12-19T15:20:44-08:00"
19
+		},
20
+		{
21
+			"path": "github.com/osrg/gobgp/packet",
22
+			"revision": "f41f0b638276dc63949e437d9c0c5bbf8a3b37b0",
23
+			"revisionTime": "2016-02-02T17:11:11-08:00"
24
+		},
25
+		{
26
+			"path": "golang.org/x/net/html",
27
+			"revision": "74d798388a60469ca4db467af4ff70242c2d9ead",
28
+			"revisionTime": "2016-02-03T00:20:23Z"
29
+		}
30
+	]
31
+}