mirror of
https://github.com/documize/community.git
synced 2025-07-23 23:29:42 +02:00
[WIP] Admin level Jira creds and vendored jira libs
This commit is contained in:
parent
0c5ec43c80
commit
7878a244d3
83 changed files with 10569 additions and 28 deletions
202
vendor/github.com/trivago/tgo/LICENSE
generated
vendored
Normal file
202
vendor/github.com/trivago/tgo/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
113
vendor/github.com/trivago/tgo/tcontainer/arrays.go
generated
vendored
Normal file
113
vendor/github.com/trivago/tgo/tcontainer/arrays.go
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2015-2016 trivago GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcontainer
|
||||
|
||||
import "sort"
|
||||
|
||||
// Int64Slice is a typedef to allow sortable int64 slices
|
||||
type Int64Slice []int64
|
||||
|
||||
func (s Int64Slice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s Int64Slice) Less(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
||||
func (s Int64Slice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Sort is a shortcut for sort.Sort(s)
|
||||
func (s Int64Slice) Sort() {
|
||||
sort.Sort(s)
|
||||
}
|
||||
|
||||
// IsSorted is a shortcut for sort.IsSorted(s)
|
||||
func (s Int64Slice) IsSorted() bool {
|
||||
return sort.IsSorted(s)
|
||||
}
|
||||
|
||||
// Set sets all values in this slice to the given value
|
||||
func (s Int64Slice) Set(v int64) {
|
||||
for i := range s {
|
||||
s[i] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Uint64Slice is a typedef to allow sortable uint64 slices
|
||||
type Uint64Slice []uint64
|
||||
|
||||
func (s Uint64Slice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s Uint64Slice) Less(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
||||
func (s Uint64Slice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Sort is a shortcut for sort.Sort(s)
|
||||
func (s Uint64Slice) Sort() {
|
||||
sort.Sort(s)
|
||||
}
|
||||
|
||||
// IsSorted is a shortcut for sort.IsSorted(s)
|
||||
func (s Uint64Slice) IsSorted() bool {
|
||||
return sort.IsSorted(s)
|
||||
}
|
||||
|
||||
// Set sets all values in this slice to the given value
|
||||
func (s Uint64Slice) Set(v uint64) {
|
||||
for i := range s {
|
||||
s[i] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Float32Slice is a typedef to allow sortable float32 slices
|
||||
type Float32Slice []float32
|
||||
|
||||
func (s Float32Slice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s Float32Slice) Less(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
||||
func (s Float32Slice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
// Sort is a shortcut for sort.Sort(s)
|
||||
func (s Float32Slice) Sort() {
|
||||
sort.Sort(s)
|
||||
}
|
||||
|
||||
// IsSorted is a shortcut for sort.IsSorted(s)
|
||||
func (s Float32Slice) IsSorted() bool {
|
||||
return sort.IsSorted(s)
|
||||
}
|
||||
|
||||
// Set sets all values in this slice to the given value
|
||||
func (s Float32Slice) Set(v float32) {
|
||||
for i := range s {
|
||||
s[i] = v
|
||||
}
|
||||
}
|
157
vendor/github.com/trivago/tgo/tcontainer/bytepool.go
generated
vendored
Normal file
157
vendor/github.com/trivago/tgo/tcontainer/bytepool.go
generated
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
// Copyright 2015-2016 trivago GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcontainer
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
tiny = 64
|
||||
small = 512
|
||||
medium = 1024
|
||||
large = 1024 * 10
|
||||
huge = 1024 * 100
|
||||
|
||||
tinyCount = 16384 // 1 MB
|
||||
smallCount = 2048 // 1 MB
|
||||
mediumCount = 1024 // 1 MB
|
||||
largeCount = 102 // ~1 MB
|
||||
hugeCount = 10 // ~1 MB
|
||||
)
|
||||
|
||||
type byteSlab struct {
|
||||
buffer []byte
|
||||
bufferSize uintptr
|
||||
stride uintptr
|
||||
basePtr *uintptr
|
||||
nextPtr *uintptr
|
||||
}
|
||||
|
||||
// BytePool is a fragmentation friendly way to allocated byte slices.
|
||||
type BytePool struct {
|
||||
tinySlab byteSlab
|
||||
smallSlab byteSlab
|
||||
mediumSlab byteSlab
|
||||
largeSlab byteSlab
|
||||
hugeSlab byteSlab
|
||||
}
|
||||
|
||||
func newByteSlab(size, count int) byteSlab {
|
||||
bufferSize := count * size
|
||||
buffer := make([]byte, bufferSize)
|
||||
basePtr := (*reflect.SliceHeader)(unsafe.Pointer(&buffer)).Data
|
||||
nextPtr := basePtr + uintptr(bufferSize)
|
||||
|
||||
return byteSlab{
|
||||
buffer: buffer,
|
||||
bufferSize: uintptr(bufferSize),
|
||||
stride: uintptr(size),
|
||||
basePtr: &basePtr,
|
||||
nextPtr: &nextPtr,
|
||||
}
|
||||
}
|
||||
|
||||
func (slab *byteSlab) getSlice(size int) (chunk []byte) {
|
||||
chunkHeader := (*reflect.SliceHeader)(unsafe.Pointer(&chunk))
|
||||
chunkHeader.Len = size
|
||||
chunkHeader.Cap = int(slab.stride)
|
||||
|
||||
for {
|
||||
// WARNING: The following two lines are order sensitive
|
||||
basePtr := atomic.LoadUintptr(slab.basePtr)
|
||||
nextPtr := atomic.AddUintptr(slab.nextPtr, -slab.stride)
|
||||
lastPtr := basePtr + slab.bufferSize
|
||||
|
||||
switch {
|
||||
case nextPtr < basePtr || nextPtr >= lastPtr:
|
||||
// out of range either means alloc while realloc or race between
|
||||
// base and next during realloc. In the latter case we lose a chunk.
|
||||
runtime.Gosched()
|
||||
|
||||
case nextPtr == basePtr:
|
||||
// Last item: realloc
|
||||
slab.buffer = make([]byte, slab.bufferSize)
|
||||
dataPtr := (*reflect.SliceHeader)(unsafe.Pointer(&slab.buffer)).Data
|
||||
|
||||
// WARNING: The following two lines are order sensitive
|
||||
atomic.StoreUintptr(slab.nextPtr, dataPtr+slab.bufferSize)
|
||||
atomic.StoreUintptr(slab.basePtr, dataPtr)
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
chunkHeader.Data = nextPtr
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewBytePool creates a new BytePool with each slab using 1 MB of storage.
|
||||
// The pool contains 5 slabs of different sizes: 64B, 512B, 1KB, 10KB and 100KB.
|
||||
// Allocations above 100KB will be allocated directly.
|
||||
func NewBytePool() BytePool {
|
||||
return BytePool{
|
||||
tinySlab: newByteSlab(tiny, tinyCount),
|
||||
smallSlab: newByteSlab(small, smallCount),
|
||||
mediumSlab: newByteSlab(medium, mediumCount),
|
||||
largeSlab: newByteSlab(large, largeCount),
|
||||
hugeSlab: newByteSlab(huge, hugeCount),
|
||||
}
|
||||
}
|
||||
|
||||
// NewBytePoolWithSize creates a new BytePool with each slab size using n MB of
|
||||
// storage. See NewBytePool() for slab size details.
|
||||
func NewBytePoolWithSize(n int) BytePool {
|
||||
if n <= 0 {
|
||||
n = 1
|
||||
}
|
||||
return BytePool{
|
||||
tinySlab: newByteSlab(tiny, tinyCount*n),
|
||||
smallSlab: newByteSlab(small, smallCount*n),
|
||||
mediumSlab: newByteSlab(medium, mediumCount*n),
|
||||
largeSlab: newByteSlab(large, largeCount*n),
|
||||
hugeSlab: newByteSlab(huge, hugeCount*n),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a slice allocated to a normalized size.
|
||||
// Sizes are organized in evenly sized buckets so that fragmentation is kept low.
|
||||
func (b *BytePool) Get(size int) []byte {
|
||||
switch {
|
||||
case size == 0:
|
||||
return []byte{}
|
||||
|
||||
case size <= tiny:
|
||||
return b.tinySlab.getSlice(size)
|
||||
|
||||
case size <= small:
|
||||
return b.smallSlab.getSlice(size)
|
||||
|
||||
case size <= medium:
|
||||
return b.mediumSlab.getSlice(size)
|
||||
|
||||
case size <= large:
|
||||
return b.largeSlab.getSlice(size)
|
||||
|
||||
case size <= huge:
|
||||
return b.hugeSlab.getSlice(size)
|
||||
|
||||
default:
|
||||
return make([]byte, size)
|
||||
}
|
||||
}
|
464
vendor/github.com/trivago/tgo/tcontainer/marshalmap.go
generated
vendored
Normal file
464
vendor/github.com/trivago/tgo/tcontainer/marshalmap.go
generated
vendored
Normal file
|
@ -0,0 +1,464 @@
|
|||
// Copyright 2015-2016 trivago GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcontainer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/trivago/tgo/treflect"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MarshalMap is a wrapper type to attach converter methods to maps normally
|
||||
// returned by marshalling methods, i.e. key/value parsers.
|
||||
// All methods that do a conversion will return an error if the value stored
|
||||
// behind key is not of the expected type or if the key is not existing in the
|
||||
// map.
|
||||
type MarshalMap map[string]interface{}
|
||||
|
||||
const (
|
||||
// MarshalMapSeparator defines the rune used for path separation
|
||||
MarshalMapSeparator = '/'
|
||||
// MarshalMapArrayBegin defines the rune starting array index notation
|
||||
MarshalMapArrayBegin = '['
|
||||
// MarshalMapArrayEnd defines the rune ending array index notation
|
||||
MarshalMapArrayEnd = ']'
|
||||
)
|
||||
|
||||
// NewMarshalMap creates a new marshal map (string -> interface{})
|
||||
func NewMarshalMap() MarshalMap {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
|
||||
// TryConvertToMarshalMap converts collections to MarshalMap if possible.
|
||||
// This is a deep conversion, i.e. each element in the collection will be
|
||||
// traversed. You can pass a formatKey function that will be applied to all
|
||||
// string keys that are detected.
|
||||
func TryConvertToMarshalMap(value interface{}, formatKey func(string) string) interface{} {
|
||||
valueMeta := reflect.ValueOf(value)
|
||||
switch valueMeta.Kind() {
|
||||
default:
|
||||
return value
|
||||
|
||||
case reflect.Array, reflect.Slice:
|
||||
arrayLen := valueMeta.Len()
|
||||
converted := make([]interface{}, arrayLen)
|
||||
for i := 0; i < arrayLen; i++ {
|
||||
converted[i] = TryConvertToMarshalMap(valueMeta.Index(i).Interface(), formatKey)
|
||||
}
|
||||
return converted
|
||||
|
||||
case reflect.Map:
|
||||
converted := NewMarshalMap()
|
||||
keys := valueMeta.MapKeys()
|
||||
|
||||
for _, keyMeta := range keys {
|
||||
strKey, isString := keyMeta.Interface().(string)
|
||||
if !isString {
|
||||
continue
|
||||
}
|
||||
if formatKey != nil {
|
||||
strKey = formatKey(strKey)
|
||||
}
|
||||
val := valueMeta.MapIndex(keyMeta).Interface()
|
||||
converted[strKey] = TryConvertToMarshalMap(val, formatKey)
|
||||
}
|
||||
return converted // ### return, converted MarshalMap ###
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertToMarshalMap tries to convert a compatible map type to a marshal map.
|
||||
// Compatible types are map[interface{}]interface{}, map[string]interface{} and of
|
||||
// course MarshalMap. The same rules as for ConvertValueToMarshalMap apply.
|
||||
func ConvertToMarshalMap(value interface{}, formatKey func(string) string) (MarshalMap, error) {
|
||||
converted := TryConvertToMarshalMap(value, formatKey)
|
||||
if result, isMap := converted.(MarshalMap); isMap {
|
||||
return result, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Root value cannot be converted to MarshalMap")
|
||||
}
|
||||
|
||||
// Bool returns a value at key that is expected to be a boolean
|
||||
func (mmap MarshalMap) Bool(key string) (bool, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return false, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
boolValue, isBool := val.(bool)
|
||||
if !isBool {
|
||||
return false, fmt.Errorf(`"%s" is expected to be a boolean`, key)
|
||||
}
|
||||
return boolValue, nil
|
||||
}
|
||||
|
||||
// Uint returns a value at key that is expected to be an uint64 or compatible
|
||||
// integer value.
|
||||
func (mmap MarshalMap) Uint(key string) (uint64, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return 0, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
if intVal, isNumber := treflect.Uint64(val); isNumber {
|
||||
return intVal, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf(`"%s" is expected to be an unsigned number type`, key)
|
||||
}
|
||||
|
||||
// Int returns a value at key that is expected to be an int64 or compatible
|
||||
// integer value.
|
||||
func (mmap MarshalMap) Int(key string) (int64, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return 0, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
if intVal, isNumber := treflect.Int64(val); isNumber {
|
||||
return intVal, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf(`"%s" is expected to be a signed number type`, key)
|
||||
}
|
||||
|
||||
// Float returns a value at key that is expected to be a float64 or compatible
|
||||
// float value.
|
||||
func (mmap MarshalMap) Float(key string) (float64, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return 0, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
if floatVal, isNumber := treflect.Float64(val); isNumber {
|
||||
return floatVal, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf(`"%s" is expected to be a signed number type`, key)
|
||||
}
|
||||
|
||||
// Duration returns a value at key that is expected to be a string
|
||||
func (mmap MarshalMap) Duration(key string) (time.Duration, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return time.Duration(0), fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
switch val.(type) {
|
||||
case time.Duration:
|
||||
return val.(time.Duration), nil
|
||||
case string:
|
||||
return time.ParseDuration(val.(string))
|
||||
}
|
||||
|
||||
return time.Duration(0), fmt.Errorf(`"%s" is expected to be a duration or string`, key)
|
||||
}
|
||||
|
||||
// String returns a value at key that is expected to be a string
|
||||
func (mmap MarshalMap) String(key string) (string, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return "", fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
strValue, isString := val.(string)
|
||||
if !isString {
|
||||
return "", fmt.Errorf(`"%s" is expected to be a string`, key)
|
||||
}
|
||||
return strValue, nil
|
||||
}
|
||||
|
||||
// Array returns a value at key that is expected to be a []interface{}
|
||||
func (mmap MarshalMap) Array(key string) ([]interface{}, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
arrayValue, isArray := val.([]interface{})
|
||||
if !isArray {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be an array`, key)
|
||||
}
|
||||
return arrayValue, nil
|
||||
}
|
||||
|
||||
// Map returns a value at key that is expected to be a
|
||||
// map[interface{}]interface{}.
|
||||
func (mmap MarshalMap) Map(key string) (map[interface{}]interface{}, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
mapValue, isMap := val.(map[interface{}]interface{})
|
||||
if !isMap {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map`, key)
|
||||
}
|
||||
return mapValue, nil
|
||||
}
|
||||
|
||||
func castToStringArray(key string, value interface{}) ([]string, error) {
|
||||
switch value.(type) {
|
||||
case string:
|
||||
return []string{value.(string)}, nil
|
||||
|
||||
case []interface{}:
|
||||
arrayVal := value.([]interface{})
|
||||
stringArray := make([]string, 0, len(arrayVal))
|
||||
|
||||
for _, val := range arrayVal {
|
||||
strValue, isString := val.(string)
|
||||
if !isString {
|
||||
return nil, fmt.Errorf(`"%s" does not contain string keys`, key)
|
||||
}
|
||||
stringArray = append(stringArray, strValue)
|
||||
}
|
||||
return stringArray, nil
|
||||
|
||||
case []string:
|
||||
return value.([]string), nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf(`"%s" is not a valid string array type`, key)
|
||||
}
|
||||
}
|
||||
|
||||
// StringArray returns a value at key that is expected to be a []string
|
||||
// This function supports conversion (by copy) from
|
||||
// * []interface{}
|
||||
func (mmap MarshalMap) StringArray(key string) ([]string, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
return castToStringArray(key, val)
|
||||
}
|
||||
|
||||
func castToInt64Array(key string, value interface{}) ([]int64, error) {
|
||||
switch value.(type) {
|
||||
case int:
|
||||
return []int64{value.(int64)}, nil
|
||||
|
||||
case []interface{}:
|
||||
arrayVal := value.([]interface{})
|
||||
intArray := make([]int64, 0, len(arrayVal))
|
||||
|
||||
for _, val := range arrayVal {
|
||||
intValue, isInt := val.(int64)
|
||||
if !isInt {
|
||||
return nil, fmt.Errorf(`"%s" does not contain int keys`, key)
|
||||
}
|
||||
intArray = append(intArray, intValue)
|
||||
}
|
||||
return intArray, nil
|
||||
|
||||
case []int64:
|
||||
return value.([]int64), nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf(`"%s" is not a valid string array type`, key)
|
||||
}
|
||||
}
|
||||
|
||||
// IntArray returns a value at key that is expected to be a []int64
|
||||
// This function supports conversion (by copy) from
|
||||
// * []interface{}
|
||||
func (mmap MarshalMap) Int64Array(key string) ([]int64, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
return castToInt64Array(key, val)
|
||||
}
|
||||
|
||||
// StringMap returns a value at key that is expected to be a map[string]string.
|
||||
// This function supports conversion (by copy) from
|
||||
// * map[interface{}]interface{}
|
||||
// * map[string]interface{}
|
||||
func (mmap MarshalMap) StringMap(key string) (map[string]string, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
switch val.(type) {
|
||||
case map[string]string:
|
||||
return val.(map[string]string), nil
|
||||
|
||||
default:
|
||||
valueMeta := reflect.ValueOf(val)
|
||||
if valueMeta.Kind() != reflect.Map {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map[string]string but is %T`, key, val)
|
||||
}
|
||||
|
||||
result := make(map[string]string)
|
||||
for _, keyMeta := range valueMeta.MapKeys() {
|
||||
strKey, isString := keyMeta.Interface().(string)
|
||||
if !isString {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map[string]string. Key is not a string`, key)
|
||||
}
|
||||
|
||||
value := valueMeta.MapIndex(keyMeta)
|
||||
strValue, isString := value.Interface().(string)
|
||||
if !isString {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map[string]string. Value is not a string`, key)
|
||||
}
|
||||
|
||||
result[strKey] = strValue
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// StringArrayMap returns a value at key that is expected to be a
|
||||
// map[string][]string. This function supports conversion (by copy) from
|
||||
// * map[interface{}][]interface{}
|
||||
// * map[interface{}]interface{}
|
||||
// * map[string]interface{}
|
||||
func (mmap MarshalMap) StringArrayMap(key string) (map[string][]string, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
switch val.(type) {
|
||||
case map[string][]string:
|
||||
return val.(map[string][]string), nil
|
||||
|
||||
default:
|
||||
valueMeta := reflect.ValueOf(val)
|
||||
if valueMeta.Kind() != reflect.Map {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map[string][]string but is %T`, key, val)
|
||||
}
|
||||
|
||||
result := make(map[string][]string)
|
||||
for _, keyMeta := range valueMeta.MapKeys() {
|
||||
strKey, isString := keyMeta.Interface().(string)
|
||||
if !isString {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map[string][]string. Key is not a string`, key)
|
||||
}
|
||||
|
||||
value := valueMeta.MapIndex(keyMeta)
|
||||
arrayValue, err := castToStringArray(strKey, value.Interface())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`"%s" is expected to be a map[string][]string. Value is not a []string`, key)
|
||||
}
|
||||
|
||||
result[strKey] = arrayValue
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalMap returns a value at key that is expected to be another MarshalMap
|
||||
// This function supports conversion (by copy) from
|
||||
// * map[interface{}]interface{}
|
||||
func (mmap MarshalMap) MarshalMap(key string) (MarshalMap, error) {
|
||||
val, exists := mmap.Value(key)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf(`"%s" is not set`, key)
|
||||
}
|
||||
|
||||
return ConvertToMarshalMap(val, nil)
|
||||
}
|
||||
|
||||
// Value returns a value from a given value path.
|
||||
// Fields can be accessed by their name. Nested fields can be accessed by using
|
||||
// "/" as a separator. Arrays can be addressed using the standard array
|
||||
// notation "[<index>]".
|
||||
// Examples:
|
||||
// "key" -> mmap["key"] single value
|
||||
// "key1/key2" -> mmap["key1"]["key2"] nested map
|
||||
// "key1[0]" -> mmap["key1"][0] nested array
|
||||
// "key1[0]key2" -> mmap["key1"][0]["key2"] nested array, nested map
|
||||
func (mmap MarshalMap) Value(key string) (interface{}, bool) {
|
||||
return mmap.resolvePath(key, mmap)
|
||||
}
|
||||
|
||||
func (mmap MarshalMap) resolvePathKey(key string) (int, int) {
|
||||
keyEnd := len(key)
|
||||
nextKeyStart := keyEnd
|
||||
pathIdx := strings.IndexRune(key, MarshalMapSeparator)
|
||||
arrayIdx := strings.IndexRune(key, MarshalMapArrayBegin)
|
||||
|
||||
if pathIdx > -1 && pathIdx < keyEnd {
|
||||
keyEnd = pathIdx
|
||||
nextKeyStart = pathIdx + 1 // don't include slash
|
||||
}
|
||||
if arrayIdx > -1 && arrayIdx < keyEnd {
|
||||
keyEnd = arrayIdx
|
||||
nextKeyStart = arrayIdx // include bracket because of multidimensional arrays
|
||||
}
|
||||
|
||||
// a -> key: "a", remain: "" -- value
|
||||
// a/b/c -> key: "a", remain: "b/c" -- nested map
|
||||
// a[1]b/c -> key: "a", remain: "[1]b/c" -- nested array
|
||||
|
||||
return keyEnd, nextKeyStart
|
||||
}
|
||||
|
||||
func (mmap MarshalMap) resolvePath(key string, value interface{}) (interface{}, bool) {
|
||||
if len(key) == 0 {
|
||||
return value, true // ### return, found requested value ###
|
||||
}
|
||||
|
||||
valueMeta := reflect.ValueOf(value)
|
||||
switch valueMeta.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
startIdx := strings.IndexRune(key, MarshalMapArrayBegin) // Must be first char, otherwise malformed
|
||||
endIdx := strings.IndexRune(key, MarshalMapArrayEnd) // Must be > startIdx, otherwise malformed
|
||||
|
||||
if startIdx == -1 || endIdx == -1 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if startIdx == 0 && endIdx > startIdx {
|
||||
index, err := strconv.Atoi(key[startIdx+1 : endIdx])
|
||||
|
||||
// [1] -> index: "1", remain: "" -- value
|
||||
// [1]a/b -> index: "1", remain: "a/b" -- nested map
|
||||
// [1][2] -> index: "1", remain: "[2]" -- nested array
|
||||
|
||||
if err == nil && index < valueMeta.Len() {
|
||||
item := valueMeta.Index(index).Interface()
|
||||
key := key[endIdx+1:]
|
||||
return mmap.resolvePath(key, item) // ### return, nested array ###
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
keyMeta := reflect.ValueOf(key)
|
||||
if storedValue := valueMeta.MapIndex(keyMeta); storedValue.IsValid() {
|
||||
return storedValue.Interface(), true
|
||||
}
|
||||
|
||||
keyEnd, nextKeyStart := mmap.resolvePathKey(key)
|
||||
pathKey := key[:keyEnd]
|
||||
keyMeta = reflect.ValueOf(pathKey)
|
||||
|
||||
if storedValue := valueMeta.MapIndex(keyMeta); storedValue.IsValid() {
|
||||
remain := key[nextKeyStart:]
|
||||
return mmap.resolvePath(remain, storedValue.Interface()) // ### return, nested map ###
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
227
vendor/github.com/trivago/tgo/tcontainer/trie.go
generated
vendored
Normal file
227
vendor/github.com/trivago/tgo/tcontainer/trie.go
generated
vendored
Normal file
|
@ -0,0 +1,227 @@
|
|||
// Copyright 2015-2016 trivago GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package tcontainer
|
||||
|
||||
// TrieNode represents a single node inside a trie.
|
||||
// Each node can contain a payload which can be retrieved after a successfull
|
||||
// match. In addition to that PathLen will contain the length of the match.
|
||||
type TrieNode struct {
|
||||
suffix []byte
|
||||
children []*TrieNode
|
||||
longestPath int
|
||||
PathLen int
|
||||
Payload interface{}
|
||||
}
|
||||
|
||||
// NewTrie creates a new root TrieNode
|
||||
func NewTrie(data []byte, payload interface{}) *TrieNode {
|
||||
return &TrieNode{
|
||||
suffix: data,
|
||||
children: []*TrieNode{},
|
||||
longestPath: len(data),
|
||||
PathLen: len(data),
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
func (node *TrieNode) addNewChild(data []byte, payload interface{}, pathLen int) {
|
||||
if node.longestPath < pathLen {
|
||||
node.longestPath = pathLen
|
||||
}
|
||||
|
||||
idx := len(node.children)
|
||||
node.children = append(node.children, nil)
|
||||
|
||||
for idx > 0 {
|
||||
nextIdx := idx - 1
|
||||
if node.children[nextIdx].longestPath > pathLen {
|
||||
break
|
||||
}
|
||||
node.children[idx] = node.children[nextIdx]
|
||||
idx = nextIdx
|
||||
}
|
||||
|
||||
node.children[idx] = &TrieNode{
|
||||
suffix: data,
|
||||
children: []*TrieNode{},
|
||||
longestPath: pathLen,
|
||||
PathLen: pathLen,
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
func (node *TrieNode) replace(oldChild *TrieNode, newChild *TrieNode) {
|
||||
for i, child := range node.children {
|
||||
if child == oldChild {
|
||||
node.children[i] = newChild
|
||||
return // ### return, replaced ###
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ForEach applies a function to each node in the tree including and below the
|
||||
// passed node.
|
||||
func (node *TrieNode) ForEach(callback func(*TrieNode)) {
|
||||
callback(node)
|
||||
for _, child := range node.children {
|
||||
child.ForEach(callback)
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a new data path to the trie.
|
||||
// The TrieNode returned is the (new) root node so you should always reassign
|
||||
// the root with the return value of Add.
|
||||
func (node *TrieNode) Add(data []byte, payload interface{}) *TrieNode {
|
||||
return node.addPath(data, payload, len(data), nil)
|
||||
}
|
||||
|
||||
func (node *TrieNode) addPath(data []byte, payload interface{}, pathLen int, parent *TrieNode) *TrieNode {
|
||||
dataLen := len(data)
|
||||
suffixLen := len(node.suffix)
|
||||
testLen := suffixLen
|
||||
if dataLen < suffixLen {
|
||||
testLen = dataLen
|
||||
}
|
||||
|
||||
var splitIdx int
|
||||
for splitIdx = 0; splitIdx < testLen; splitIdx++ {
|
||||
if data[splitIdx] != node.suffix[splitIdx] {
|
||||
break // ### break, split found ###
|
||||
}
|
||||
}
|
||||
|
||||
if splitIdx == suffixLen {
|
||||
// Continue down or stop here (full suffix match)
|
||||
|
||||
if splitIdx == dataLen {
|
||||
node.Payload = payload // may overwrite
|
||||
return node // ### return, path already stored ###
|
||||
}
|
||||
|
||||
data = data[splitIdx:]
|
||||
if suffixLen > 0 {
|
||||
for _, child := range node.children {
|
||||
if child.suffix[0] == data[0] {
|
||||
child.addPath(data, payload, pathLen, node)
|
||||
return node // ### return, continue on path ###
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.addNewChild(data, payload, pathLen)
|
||||
return node // ### return, new leaf ###
|
||||
}
|
||||
|
||||
if splitIdx == dataLen {
|
||||
// Make current node a subpath of new data node (full data match)
|
||||
// This case implies that dataLen < suffixLen as splitIdx == suffixLen
|
||||
// did not match.
|
||||
|
||||
node.suffix = node.suffix[splitIdx:]
|
||||
|
||||
newParent := NewTrie(data, payload)
|
||||
newParent.PathLen = pathLen
|
||||
newParent.longestPath = node.longestPath
|
||||
newParent.children = []*TrieNode{node}
|
||||
|
||||
if parent != nil {
|
||||
parent.replace(node, newParent)
|
||||
}
|
||||
return newParent // ### return, rotation ###
|
||||
}
|
||||
|
||||
// New parent required with both nodes as children (partial match)
|
||||
|
||||
node.suffix = node.suffix[splitIdx:]
|
||||
|
||||
newParent := NewTrie(data[:splitIdx], nil)
|
||||
newParent.PathLen = 0
|
||||
newParent.longestPath = node.longestPath
|
||||
newParent.children = []*TrieNode{node}
|
||||
newParent.addNewChild(data[splitIdx:], payload, pathLen)
|
||||
|
||||
if parent != nil {
|
||||
parent.replace(node, newParent)
|
||||
}
|
||||
return newParent // ### return, new parent ###
|
||||
}
|
||||
|
||||
// Match compares the trie to the given data stream.
|
||||
// Match returns true if data can be completely matched to the trie.
|
||||
func (node *TrieNode) Match(data []byte) *TrieNode {
|
||||
dataLen := len(data)
|
||||
suffixLen := len(node.suffix)
|
||||
if dataLen < suffixLen {
|
||||
return nil // ### return, cannot be fully matched ###
|
||||
}
|
||||
|
||||
for i := 0; i < suffixLen; i++ {
|
||||
if data[i] != node.suffix[i] {
|
||||
return nil // ### return, no match ###
|
||||
}
|
||||
}
|
||||
|
||||
if dataLen == suffixLen {
|
||||
if node.PathLen > 0 {
|
||||
return node // ### return, full match ###
|
||||
}
|
||||
return nil // ### return, invalid match ###
|
||||
}
|
||||
|
||||
data = data[suffixLen:]
|
||||
numChildren := len(node.children)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
matchedNode := node.children[i].Match(data)
|
||||
if matchedNode != nil {
|
||||
return matchedNode // ### return, match found ###
|
||||
}
|
||||
}
|
||||
|
||||
return nil // ### return, no valid path ###
|
||||
}
|
||||
|
||||
// MatchStart compares the trie to the beginning of the given data stream.
|
||||
// MatchStart returns true if the beginning of data can be matched to the trie.
|
||||
func (node *TrieNode) MatchStart(data []byte) *TrieNode {
|
||||
dataLen := len(data)
|
||||
suffixLen := len(node.suffix)
|
||||
if dataLen < suffixLen {
|
||||
return nil // ### return, cannot be fully matched ###
|
||||
}
|
||||
|
||||
for i := 0; i < suffixLen; i++ {
|
||||
if data[i] != node.suffix[i] {
|
||||
return nil // ### return, no match ###
|
||||
}
|
||||
}
|
||||
|
||||
// Match longest path first
|
||||
|
||||
data = data[suffixLen:]
|
||||
numChildren := len(node.children)
|
||||
for i := 0; i < numChildren; i++ {
|
||||
matchedNode := node.children[i].MatchStart(data)
|
||||
if matchedNode != nil {
|
||||
return matchedNode // ### return, match found ###
|
||||
}
|
||||
}
|
||||
|
||||
// May be only a part of data but we have a valid match
|
||||
|
||||
if node.PathLen > 0 {
|
||||
return node // ### return, full match ###
|
||||
}
|
||||
return nil // ### return, no valid path ###
|
||||
}
|
373
vendor/github.com/trivago/tgo/treflect/reflection.go
generated
vendored
Normal file
373
vendor/github.com/trivago/tgo/treflect/reflection.go
generated
vendored
Normal file
|
@ -0,0 +1,373 @@
|
|||
// Copyright 2015-2016 trivago GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package treflect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// GetMissingMethods checks if a given object implements all methods of a
|
||||
// given interface. It returns the interface coverage [0..1] as well as an array
|
||||
// of error messages. If the interface is correctly implemented the coverage is
|
||||
// 1 and the error message array is empty.
|
||||
func GetMissingMethods(objType reflect.Type, ifaceType reflect.Type) (float32, []string) {
|
||||
missing := []string{}
|
||||
if objType.Implements(ifaceType) {
|
||||
return 1.0, missing
|
||||
}
|
||||
|
||||
methodCount := ifaceType.NumMethod()
|
||||
for mIdx := 0; mIdx < methodCount; mIdx++ {
|
||||
ifaceMethod := ifaceType.Method(mIdx)
|
||||
objMethod, exists := objType.MethodByName(ifaceMethod.Name)
|
||||
signatureMismatch := false
|
||||
|
||||
switch {
|
||||
case !exists:
|
||||
missing = append(missing, fmt.Sprintf("Missing: \"%s\" %v", ifaceMethod.Name, ifaceMethod.Type))
|
||||
continue // ### continue, error found ###
|
||||
|
||||
case ifaceMethod.Type.NumOut() != objMethod.Type.NumOut():
|
||||
signatureMismatch = true
|
||||
|
||||
case ifaceMethod.Type.NumIn()+1 != objMethod.Type.NumIn():
|
||||
signatureMismatch = true
|
||||
|
||||
default:
|
||||
for oIdx := 0; !signatureMismatch && oIdx < ifaceMethod.Type.NumOut(); oIdx++ {
|
||||
signatureMismatch = ifaceMethod.Type.Out(oIdx) != objMethod.Type.Out(oIdx)
|
||||
}
|
||||
for iIdx := 0; !signatureMismatch && iIdx < ifaceMethod.Type.NumIn(); iIdx++ {
|
||||
signatureMismatch = ifaceMethod.Type.In(iIdx) != objMethod.Type.In(iIdx+1)
|
||||
}
|
||||
}
|
||||
|
||||
if signatureMismatch {
|
||||
missing = append(missing, fmt.Sprintf("Invalid: \"%s\" %v is not %v", ifaceMethod.Name, objMethod.Type, ifaceMethod.Type))
|
||||
}
|
||||
}
|
||||
|
||||
return float32(methodCount-len(missing)) / float32(methodCount), missing
|
||||
}
|
||||
|
||||
// Int64 converts any signed number type to an int64.
|
||||
// The second parameter is returned as false if a non-number type was given.
|
||||
func Int64(v interface{}) (int64, bool) {
|
||||
|
||||
switch reflect.TypeOf(v).Kind() {
|
||||
case reflect.Int:
|
||||
return int64(v.(int)), true
|
||||
case reflect.Int8:
|
||||
return int64(v.(int8)), true
|
||||
case reflect.Int16:
|
||||
return int64(v.(int16)), true
|
||||
case reflect.Int32:
|
||||
return int64(v.(int32)), true
|
||||
case reflect.Int64:
|
||||
return v.(int64), true
|
||||
case reflect.Float32:
|
||||
return int64(v.(float32)), true
|
||||
case reflect.Float64:
|
||||
return int64(v.(float64)), true
|
||||
}
|
||||
|
||||
fmt.Printf("%t\n%#v\n%#v\n", v, v, reflect.TypeOf(v).Kind())
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Uint64 converts any unsigned number type to an uint64.
|
||||
// The second parameter is returned as false if a non-number type was given.
|
||||
func Uint64(v interface{}) (uint64, bool) {
|
||||
|
||||
switch reflect.TypeOf(v).Kind() {
|
||||
case reflect.Uint:
|
||||
return uint64(v.(uint)), true
|
||||
case reflect.Uint8:
|
||||
return uint64(v.(uint8)), true
|
||||
case reflect.Uint16:
|
||||
return uint64(v.(uint16)), true
|
||||
case reflect.Uint32:
|
||||
return uint64(v.(uint32)), true
|
||||
case reflect.Uint64:
|
||||
return v.(uint64), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Float32 converts any number type to an float32.
|
||||
// The second parameter is returned as false if a non-number type was given.
|
||||
func Float32(v interface{}) (float32, bool) {
|
||||
|
||||
switch reflect.TypeOf(v).Kind() {
|
||||
case reflect.Int:
|
||||
return float32(v.(int)), true
|
||||
case reflect.Uint:
|
||||
return float32(v.(uint)), true
|
||||
case reflect.Int8:
|
||||
return float32(v.(int8)), true
|
||||
case reflect.Uint8:
|
||||
return float32(v.(uint8)), true
|
||||
case reflect.Int16:
|
||||
return float32(v.(int16)), true
|
||||
case reflect.Uint16:
|
||||
return float32(v.(uint16)), true
|
||||
case reflect.Int32:
|
||||
return float32(v.(int32)), true
|
||||
case reflect.Uint32:
|
||||
return float32(v.(uint32)), true
|
||||
case reflect.Int64:
|
||||
return float32(v.(int64)), true
|
||||
case reflect.Uint64:
|
||||
return float32(v.(uint64)), true
|
||||
case reflect.Float32:
|
||||
return v.(float32), true
|
||||
case reflect.Float64:
|
||||
return float32(v.(float64)), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// Float64 converts any number type to an float64.
|
||||
// The second parameter is returned as false if a non-number type was given.
|
||||
func Float64(v interface{}) (float64, bool) {
|
||||
|
||||
switch reflect.TypeOf(v).Kind() {
|
||||
case reflect.Int:
|
||||
return float64(v.(int)), true
|
||||
case reflect.Uint:
|
||||
return float64(v.(uint)), true
|
||||
case reflect.Int8:
|
||||
return float64(v.(int8)), true
|
||||
case reflect.Uint8:
|
||||
return float64(v.(uint8)), true
|
||||
case reflect.Int16:
|
||||
return float64(v.(int16)), true
|
||||
case reflect.Uint16:
|
||||
return float64(v.(uint16)), true
|
||||
case reflect.Int32:
|
||||
return float64(v.(int32)), true
|
||||
case reflect.Uint32:
|
||||
return float64(v.(uint32)), true
|
||||
case reflect.Int64:
|
||||
return float64(v.(int64)), true
|
||||
case reflect.Uint64:
|
||||
return float64(v.(uint64)), true
|
||||
case reflect.Float32:
|
||||
return float64(v.(float32)), true
|
||||
case reflect.Float64:
|
||||
return v.(float64), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// RemovePtrFromType will return the type of t and strips away any pointer(s)
|
||||
// in front of the actual type.
|
||||
func RemovePtrFromType(t interface{}) reflect.Type {
|
||||
var v reflect.Type
|
||||
if rt, isType := t.(reflect.Type); isType {
|
||||
v = rt
|
||||
} else {
|
||||
v = reflect.TypeOf(t)
|
||||
}
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// RemovePtrFromValue will return the value of t and strips away any pointer(s)
|
||||
// in front of the actual type.
|
||||
func RemovePtrFromValue(t interface{}) reflect.Value {
|
||||
var v reflect.Value
|
||||
if rv, isValue := t.(reflect.Value); isValue {
|
||||
v = rv
|
||||
} else {
|
||||
v = reflect.ValueOf(t)
|
||||
}
|
||||
for v.Type().Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// UnsafeCopy will copy data from src to dst while ignoring type information.
|
||||
// Both types need to be of the same size and dst and src have to be pointers.
|
||||
// UnsafeCopy will panic if these requirements are not met.
|
||||
func UnsafeCopy(dst, src interface{}) {
|
||||
dstValue := reflect.ValueOf(dst)
|
||||
srcValue := reflect.ValueOf(src)
|
||||
UnsafeCopyValue(dstValue, srcValue)
|
||||
}
|
||||
|
||||
// UnsafeCopyValue will copy data from src to dst while ignoring type
|
||||
// information. Both types need to be of the same size or this function will
|
||||
// panic. Also both types must support dereferencing via reflect.Elem()
|
||||
func UnsafeCopyValue(dstValue reflect.Value, srcValue reflect.Value) {
|
||||
dstType := dstValue.Elem().Type()
|
||||
srcType := srcValue.Type()
|
||||
|
||||
var srcPtr uintptr
|
||||
if srcValue.Kind() != reflect.Ptr {
|
||||
// If we don't get a pointer to our source data we need to forcefully
|
||||
// retrieve it by accessing the interface pointer. This is ok as we
|
||||
// only read from it.
|
||||
iface := srcValue.Interface()
|
||||
srcPtr = reflect.ValueOf(&iface).Elem().InterfaceData()[1] // Pointer to data
|
||||
} else {
|
||||
srcType = srcValue.Elem().Type()
|
||||
srcPtr = srcValue.Pointer()
|
||||
}
|
||||
|
||||
if dstType.Size() != srcType.Size() {
|
||||
panic("Type size mismatch between " + dstType.String() + " and " + srcType.String())
|
||||
}
|
||||
|
||||
dstAsSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: dstValue.Pointer(),
|
||||
Len: int(dstType.Size()),
|
||||
Cap: int(dstType.Size()),
|
||||
}))
|
||||
|
||||
srcAsSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: srcPtr,
|
||||
Len: int(srcType.Size()),
|
||||
Cap: int(srcType.Size()),
|
||||
}))
|
||||
|
||||
copy(dstAsSlice, srcAsSlice)
|
||||
}
|
||||
|
||||
// SetMemberByName sets member name of the given pointer-to-struct to the data
|
||||
// passed to this function. The member may be private, too.
|
||||
func SetMemberByName(ptrToStruct interface{}, name string, data interface{}) {
|
||||
structVal := reflect.Indirect(reflect.ValueOf(ptrToStruct))
|
||||
member := structVal.FieldByName(name)
|
||||
|
||||
SetValue(member, data)
|
||||
}
|
||||
|
||||
// SetMemberByIndex sets member idx of the given pointer-to-struct to the data
|
||||
// passed to this function. The member may be private, too.
|
||||
func SetMemberByIndex(ptrToStruct interface{}, idx int, data interface{}) {
|
||||
structVal := reflect.Indirect(reflect.ValueOf(ptrToStruct))
|
||||
member := structVal.Field(idx)
|
||||
|
||||
SetValue(member, data)
|
||||
}
|
||||
|
||||
// SetValue sets an addressable value to the data passed to this function.
|
||||
// In contrast to golangs reflect package this will also work with private
|
||||
// variables. Please note that this function may not support all types, yet.
|
||||
func SetValue(member reflect.Value, data interface{}) {
|
||||
if member.CanSet() {
|
||||
member.Set(reflect.ValueOf(data).Convert(member.Type()))
|
||||
return // ### return, easy way ###
|
||||
}
|
||||
|
||||
if !member.CanAddr() {
|
||||
panic("SetValue requires addressable member type")
|
||||
}
|
||||
|
||||
ptrToMember := unsafe.Pointer(member.UnsafeAddr())
|
||||
dataValue := reflect.ValueOf(data)
|
||||
|
||||
switch member.Kind() {
|
||||
case reflect.Bool:
|
||||
*(*bool)(ptrToMember) = dataValue.Bool()
|
||||
|
||||
case reflect.Uint:
|
||||
*(*uint)(ptrToMember) = uint(dataValue.Uint())
|
||||
|
||||
case reflect.Uint8:
|
||||
*(*uint8)(ptrToMember) = uint8(dataValue.Uint())
|
||||
|
||||
case reflect.Uint16:
|
||||
*(*uint16)(ptrToMember) = uint16(dataValue.Uint())
|
||||
|
||||
case reflect.Uint32:
|
||||
*(*uint32)(ptrToMember) = uint32(dataValue.Uint())
|
||||
|
||||
case reflect.Uint64:
|
||||
*(*uint64)(ptrToMember) = dataValue.Uint()
|
||||
|
||||
case reflect.Int:
|
||||
*(*int)(ptrToMember) = int(dataValue.Int())
|
||||
|
||||
case reflect.Int8:
|
||||
*(*int8)(ptrToMember) = int8(dataValue.Int())
|
||||
|
||||
case reflect.Int16:
|
||||
*(*int16)(ptrToMember) = int16(dataValue.Int())
|
||||
|
||||
case reflect.Int32:
|
||||
*(*int32)(ptrToMember) = int32(dataValue.Int())
|
||||
|
||||
case reflect.Int64:
|
||||
*(*int64)(ptrToMember) = dataValue.Int()
|
||||
|
||||
case reflect.Float32:
|
||||
*(*float32)(ptrToMember) = float32(dataValue.Float())
|
||||
|
||||
case reflect.Float64:
|
||||
*(*float64)(ptrToMember) = dataValue.Float()
|
||||
|
||||
case reflect.Complex64:
|
||||
*(*complex64)(ptrToMember) = complex64(dataValue.Complex())
|
||||
|
||||
case reflect.Complex128:
|
||||
*(*complex128)(ptrToMember) = dataValue.Complex()
|
||||
|
||||
case reflect.String:
|
||||
*(*string)(ptrToMember) = dataValue.String()
|
||||
|
||||
case reflect.Map, reflect.Chan:
|
||||
// Exploit the fact that "map" is actually "*runtime.hmap" and force
|
||||
// overwrite that pointer in the passed struct.
|
||||
// Same foes for "chan" which is actually "*runtime.hchan".
|
||||
|
||||
// Note: Assigning a map or channel to another variable does NOT copy
|
||||
// the contents so copying the pointer follows go's standard behavior.
|
||||
dataAsPtr := unsafe.Pointer(dataValue.Pointer())
|
||||
*(**uintptr)(ptrToMember) = (*uintptr)(dataAsPtr)
|
||||
|
||||
case reflect.Interface:
|
||||
// Interfaces are basically two pointers, see runtime.iface.
|
||||
// We want to modify exactly that data, which is returned by
|
||||
// the InterfaceData() method.
|
||||
|
||||
if dataValue.Kind() != reflect.Interface {
|
||||
// A type reference was passed. In order to overwrite the memory
|
||||
// Representation of an interface we need to generate it first.
|
||||
// Reflect does not allow us to do that unless we use the
|
||||
// InterfaceData method which exposes the internal representation
|
||||
// of an interface.
|
||||
interfaceData := reflect.ValueOf(&data).Elem().InterfaceData()
|
||||
dataValue = reflect.ValueOf(interfaceData)
|
||||
}
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
// Complex types are assigned memcpy style.
|
||||
// Note: This should not break the garbage collector although we cannot
|
||||
// be 100% sure on this.
|
||||
UnsafeCopyValue(member.Addr(), dataValue)
|
||||
}
|
||||
}
|
97
vendor/github.com/trivago/tgo/treflect/typeregistry.go
generated
vendored
Normal file
97
vendor/github.com/trivago/tgo/treflect/typeregistry.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2015-2016 trivago GmbH
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package treflect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TypeRegistry is a name to type registry used to create objects by name.
|
||||
type TypeRegistry struct {
|
||||
namedType map[string]reflect.Type
|
||||
}
|
||||
|
||||
// NewTypeRegistry creates a new TypeRegistry. Note that there is a global type
|
||||
// registry available in the main tgo package (tgo.TypeRegistry).
|
||||
func NewTypeRegistry() TypeRegistry {
|
||||
return TypeRegistry{
|
||||
namedType: make(map[string]reflect.Type),
|
||||
}
|
||||
}
|
||||
|
||||
// Register a plugin to the TypeRegistry by passing an uninitialized object.
|
||||
func (registry TypeRegistry) Register(typeInstance interface{}) {
|
||||
registry.RegisterWithDepth(typeInstance, 1)
|
||||
}
|
||||
|
||||
// RegisterWithDepth to register a plugin to the TypeRegistry by passing an uninitialized object.
|
||||
func (registry TypeRegistry) RegisterWithDepth(typeInstance interface{}, depth int) {
|
||||
structType := reflect.TypeOf(typeInstance)
|
||||
packageName := structType.PkgPath()
|
||||
typeName := structType.Name()
|
||||
|
||||
pathTokens := strings.Split(packageName, "/")
|
||||
maxDepth := 3
|
||||
if len(pathTokens) < maxDepth {
|
||||
maxDepth = len(pathTokens)
|
||||
}
|
||||
|
||||
for n := depth; n <= maxDepth; n++ {
|
||||
shortTypeName := strings.Join(pathTokens[len(pathTokens)-n:], ".") + "." + typeName
|
||||
registry.namedType[shortTypeName] = structType
|
||||
}
|
||||
}
|
||||
|
||||
// New creates an uninitialized object by class name.
|
||||
// The class name has to be "package.class" or "package/subpackage.class".
|
||||
// The gollum package is omitted from the package path.
|
||||
func (registry TypeRegistry) New(typeName string) (interface{}, error) {
|
||||
structType, exists := registry.namedType[typeName]
|
||||
if exists {
|
||||
return reflect.New(structType).Interface(), nil
|
||||
}
|
||||
return nil, fmt.Errorf("Unknown class: %s", typeName)
|
||||
}
|
||||
|
||||
// GetTypeOf returns only the type asscociated with the given name.
|
||||
// If the name is not registered, nil is returned.
|
||||
// The type returned will be a pointer type.
|
||||
func (registry TypeRegistry) GetTypeOf(typeName string) reflect.Type {
|
||||
if structType, exists := registry.namedType[typeName]; exists {
|
||||
return reflect.PtrTo(structType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsTypeRegistered returns true if a type is registered to this registry.
|
||||
// Note that GetTypeOf can do the same thing by checking for nil but also
|
||||
// returns the type, so in many cases you will want to call this function.
|
||||
func (registry TypeRegistry) IsTypeRegistered(typeName string) bool {
|
||||
_, exists := registry.namedType[typeName]
|
||||
return exists
|
||||
}
|
||||
|
||||
// GetRegistered returns the names of all registered types for a given package
|
||||
func (registry TypeRegistry) GetRegistered(packageName string) []string {
|
||||
var result []string
|
||||
for key := range registry.namedType {
|
||||
if strings.HasPrefix(key, packageName) {
|
||||
result = append(result, key)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue