liuxiaolong
2020-09-16 4501e38ca66f09b35aaaf43fa5a316554930fcf4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) 2012, 2013 Ugorji Nwoke. All rights reserved.
// Use of this source code is governed by a BSD-style license found in the LICENSE file.
 
package codec
 
// All non-std package dependencies live in this file,
// so porting to different environment is easy (just update functions).
 
import (
    "errors"
    "fmt"
    "math"
    "reflect"
)
 
var (
    raisePanicAfterRecover = false
    debugging              = true
)
 
func panicValToErr(panicVal interface{}, err *error) {
    switch xerr := panicVal.(type) {
    case error:
        *err = xerr
    case string:
        *err = errors.New(xerr)
    default:
        *err = fmt.Errorf("%v", panicVal)
    }
    if raisePanicAfterRecover {
        panic(panicVal)
    }
    return
}
 
func isEmptyValueDeref(v reflect.Value, deref bool) bool {
    switch v.Kind() {
    case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
        return v.Len() == 0
    case reflect.Bool:
        return !v.Bool()
    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return v.Int() == 0
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
        return v.Uint() == 0
    case reflect.Float32, reflect.Float64:
        return v.Float() == 0
    case reflect.Interface, reflect.Ptr:
        if deref {
            if v.IsNil() {
                return true
            }
            return isEmptyValueDeref(v.Elem(), deref)
        } else {
            return v.IsNil()
        }
    case reflect.Struct:
        // return true if all fields are empty. else return false.
 
        // we cannot use equality check, because some fields may be maps/slices/etc
        // and consequently the structs are not comparable.
        // return v.Interface() == reflect.Zero(v.Type()).Interface()
        for i, n := 0, v.NumField(); i < n; i++ {
            if !isEmptyValueDeref(v.Field(i), deref) {
                return false
            }
        }
        return true
    }
    return false
}
 
func isEmptyValue(v reflect.Value) bool {
    return isEmptyValueDeref(v, true)
}
 
func debugf(format string, args ...interface{}) {
    if debugging {
        if len(format) == 0 || format[len(format)-1] != '\n' {
            format = format + "\n"
        }
        fmt.Printf(format, args...)
    }
}
 
func pruneSignExt(v []byte, pos bool) (n int) {
    if len(v) < 2 {
    } else if pos && v[0] == 0 {
        for ; v[n] == 0 && n+1 < len(v) && (v[n+1]&(1<<7) == 0); n++ {
        }
    } else if !pos && v[0] == 0xff {
        for ; v[n] == 0xff && n+1 < len(v) && (v[n+1]&(1<<7) != 0); n++ {
        }
    }
    return
}
 
func implementsIntf(typ, iTyp reflect.Type) (success bool, indir int8) {
    if typ == nil {
        return
    }
    rt := typ
    // The type might be a pointer and we need to keep
    // dereferencing to the base type until we find an implementation.
    for {
        if rt.Implements(iTyp) {
            return true, indir
        }
        if p := rt; p.Kind() == reflect.Ptr {
            indir++
            if indir >= math.MaxInt8 { // insane number of indirections
                return false, 0
            }
            rt = p.Elem()
            continue
        }
        break
    }
    // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy.
    if typ.Kind() != reflect.Ptr {
        // Not a pointer, but does the pointer work?
        if reflect.PtrTo(typ).Implements(iTyp) {
            return true, -1
        }
    }
    return false, 0
}