-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
utils.go
162 lines (128 loc) · 3.6 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright (c) 2022-2024 Xelaj Software
//
// This file is a part of tl package.
// See https://github.com/xelaj/tl/blob/master/LICENSE_README.md for details.
package tl
import (
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"math"
"math/big"
"reflect"
"golang.org/x/exp/constraints"
)
type null = struct{}
func unreachable() { panic("Unreachable") } //cover:ignore
func unimplemented() { panic("Unimplemented") } //cover:ignore
func randBytes(size int) []byte { //cover:ignore
b := make([]byte, size)
rand.Read(b)
return b
}
func littleUint24Bytes(v int) []byte { //cover:ignore
return []byte{
byte(v),
byte(v >> 8), //nolint:gomnd // r u kiddin
byte(v >> 16), //nolint:gomnd // r u kiddin
}
}
// pad returns size of padding for message.
func pad(l, padSize int) int {
mod := l % padSize
return (padSize - mod) * (1 + (mod-padSize)/padSize)
}
// v is bool, pointer, interface or slice.
func isFieldContainsData(v reflect.Value) bool {
// special cases for enums
if enum, ok := v.Interface().(Object); ok && v.Kind() == reflect.Uint32 {
return enum != nil && enum.CRC() != 0
}
switch k := v.Kind(); k { //nolint:exhaustive // have default
case reflect.Bool:
return v.Bool()
case reflect.Pointer, reflect.Interface, reflect.Slice:
return !v.IsNil()
default:
panic(
fmt.Sprintf(
"something is wrong with registry, optional field must be pointer or bool, got %v",
k,
),
)
}
}
func appendMany[T any](b ...[]T) []T { //cover:ignore
var size int
for _, s := range b {
size += len(s)
}
tmp := make([]T, size)
var i int
for _, s := range b {
i += copy(tmp[i:], s)
}
return tmp
}
func as118[T error](err error) (T, bool) { //cover:ignore
var converted T
return converted, errors.As(err, &converted)
}
type convertibleNum interface {
constraints.Integer | constraints.Float
}
func convertNumErr[V, T convertibleNum](res T, err error) (V, error) { return V(res), err } //cover:ignore
type convertibleStr interface {
~string | ~[]byte
}
func convertStrErr[V, T convertibleStr](res T, err error) (V, error) { return V(res), err } //cover:ignore
func ptr[T any](value T) *T { return &value } //cover:ignore
func val[T any](value *T) T { return *value } //cover:ignore
func new[T any]() T { var t T; return t } //cover:ignore
func u32b(order binary.ByteOrder, v uint32) []byte { //cover:ignore
b := make([]byte, WordLen)
order.PutUint32(b, v)
return b
}
func u64b(order binary.ByteOrder, v uint64) []byte { //cover:ignore
b := make([]byte, LongLen)
order.PutUint64(b, v)
return b
}
func f64b(order binary.ByteOrder, v float64) []byte { //cover:ignore
b := make([]byte, LongLen)
order.PutUint64(b, math.Float64bits(v))
return b
}
// allowed bitsize is 8, 16, 32, 64, 128, 256, 512, 1024 and 2048 bits.
func bigIntBytes(v *big.Int, bitsize int) []byte {
bitsizeSquaredFloat := math.Log2(float64(bitsize))
if _, f := math.Modf(bitsizeSquaredFloat); f != 0 {
panic(fmt.Sprintf("bitsize not squaring by 2: bitsize %v", bitsize))
}
if bitsizeSquaredFloat > 11 {
panic(fmt.Sprintf("bitsize is larger than 2048 bit: bitsize %v", bitsize))
}
vbytes := v.Bytes()
vbytesLen := len(vbytes)
offset := bitsize/8 - vbytesLen
if offset < 0 {
panic(fmt.Sprintf("bitsize too small: have %v, want at least %v", bitsize, vbytes))
}
return append(make([]byte, offset), vbytes...)
}
func maybeNil(v reflect.Value) bool {
switch v.Kind() { //nolint:exhaustive // has default statement
case reflect.Chan,
reflect.Func,
reflect.Map,
reflect.Pointer,
reflect.UnsafePointer,
reflect.Interface,
reflect.Slice:
return v.IsNil()
default:
return false
}
}