mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
Compare commits
7 Commits
v2.3.7
...
385e64cc52
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
385e64cc52 | ||
|
|
be45a259db | ||
|
|
6f703fe577 | ||
|
|
cb8d93c499 | ||
|
|
ae1014c572 | ||
|
|
d5b9e67330 | ||
|
|
a81403766f |
@@ -228,6 +228,42 @@ func ToPointer[T any](value T) *T {
|
||||
return &value
|
||||
}
|
||||
|
||||
// ToPointers convert a slice of values to a slice of pointers.
|
||||
// Play: todo
|
||||
func ToPointers[T any](values []T) []*T {
|
||||
result := make([]*T, len(values))
|
||||
for i := range values {
|
||||
result[i] = &values[i]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// FromPointer returns the value pointed to by the pointer.
|
||||
// Play: todo
|
||||
func FromPointer[T any](ptr *T) T {
|
||||
if ptr == nil {
|
||||
var zeroValue T
|
||||
return zeroValue
|
||||
}
|
||||
|
||||
return *ptr
|
||||
}
|
||||
|
||||
// FromPointers convert a slice of pointers to a slice of values.
|
||||
// Play: todo
|
||||
func FromPointers[T any](pointers []*T) []T {
|
||||
result := make([]T, len(pointers))
|
||||
for i, ptr := range pointers {
|
||||
if ptr == nil {
|
||||
var zeroValue T
|
||||
result[i] = zeroValue
|
||||
} else {
|
||||
result[i] = *ptr
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ToMap convert a slice of structs to a map based on iteratee function.
|
||||
// Play: https://go.dev/play/p/tVFy7E-t24l
|
||||
func ToMap[T any, K comparable, V any](array []T, iteratee func(T) (K, V)) map[K]V {
|
||||
@@ -406,15 +442,15 @@ func ToStdBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
return base64.StdEncoding.EncodeToString(value.([]byte))
|
||||
return base64.StdEncoding.EncodeToString(v)
|
||||
case string:
|
||||
return base64.StdEncoding.EncodeToString([]byte(value.(string)))
|
||||
return base64.StdEncoding.EncodeToString([]byte(v))
|
||||
case error:
|
||||
return base64.StdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
return base64.StdEncoding.EncodeToString([]byte(v.Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
marshal, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
@@ -428,15 +464,15 @@ func ToUrlBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
return base64.URLEncoding.EncodeToString(value.([]byte))
|
||||
return base64.URLEncoding.EncodeToString(v)
|
||||
case string:
|
||||
return base64.URLEncoding.EncodeToString([]byte(value.(string)))
|
||||
return base64.URLEncoding.EncodeToString([]byte(v))
|
||||
case error:
|
||||
return base64.URLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
return base64.URLEncoding.EncodeToString([]byte(v.Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
marshal, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
@@ -450,7 +486,7 @@ func ToRawStdBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
return base64.RawStdEncoding.EncodeToString(value.([]byte))
|
||||
case string:
|
||||
@@ -458,7 +494,7 @@ func ToRawStdBase64(value any) string {
|
||||
case error:
|
||||
return base64.RawStdEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
marshal, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
@@ -472,7 +508,7 @@ func ToRawUrlBase64(value any) string {
|
||||
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||
return ""
|
||||
}
|
||||
switch value.(type) {
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
return base64.RawURLEncoding.EncodeToString(value.([]byte))
|
||||
case string:
|
||||
@@ -480,7 +516,7 @@ func ToRawUrlBase64(value any) string {
|
||||
case error:
|
||||
return base64.RawURLEncoding.EncodeToString([]byte(value.(error).Error()))
|
||||
default:
|
||||
marshal, err := json.Marshal(value)
|
||||
marshal, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -302,6 +302,75 @@ func TestToPointer(t *testing.T) {
|
||||
assert.Equal(*result, 123)
|
||||
}
|
||||
|
||||
func TestToPointers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestToPointers")
|
||||
|
||||
intVals := []int{1, 2, 3}
|
||||
result := ToPointers(intVals)
|
||||
|
||||
assert.Equal(3, len(result))
|
||||
assert.Equal(1, *result[0])
|
||||
assert.Equal(2, *result[1])
|
||||
assert.Equal(3, *result[2])
|
||||
|
||||
stringVals := []string{"a", "b", "c"}
|
||||
resultStr := ToPointers(stringVals)
|
||||
assert.Equal(3, len(resultStr))
|
||||
assert.Equal("a", *resultStr[0])
|
||||
assert.Equal("b", *resultStr[1])
|
||||
assert.Equal("c", *resultStr[2])
|
||||
}
|
||||
|
||||
func TestFromPointer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestFromPointer")
|
||||
|
||||
intVal := 123
|
||||
pointer := &intVal
|
||||
result := FromPointer(pointer)
|
||||
|
||||
assert.Equal(123, result)
|
||||
|
||||
stringVal := "abc"
|
||||
stringPointer := &stringVal
|
||||
resultStr := FromPointer(stringPointer)
|
||||
|
||||
assert.Equal("abc", resultStr)
|
||||
}
|
||||
|
||||
func TestFromPointers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestFromPointers")
|
||||
|
||||
intPointers := []*int{new(int), new(int), new(int)}
|
||||
*intPointers[0] = 1
|
||||
*intPointers[1] = 2
|
||||
*intPointers[2] = 3
|
||||
|
||||
result := FromPointers(intPointers)
|
||||
|
||||
assert.Equal(3, len(result))
|
||||
assert.Equal(1, result[0])
|
||||
assert.Equal(2, result[1])
|
||||
assert.Equal(3, result[2])
|
||||
|
||||
stringPointers := []*string{new(string), new(string), new(string)}
|
||||
*stringPointers[0] = "a"
|
||||
*stringPointers[1] = "b"
|
||||
*stringPointers[2] = "c"
|
||||
|
||||
resultStr := FromPointers(stringPointers)
|
||||
|
||||
assert.Equal(3, len(resultStr))
|
||||
assert.Equal("a", resultStr[0])
|
||||
assert.Equal("b", resultStr[1])
|
||||
assert.Equal("c", resultStr[2])
|
||||
}
|
||||
|
||||
func TestEncodeByte(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
-----BEGIN rsa private key-----
|
||||
MIIJKAIBAAKCAgEAw0anfgtraA2uaZwoLpLBvo1EkfYvDBgeXoMQ4WMKbcw6jU8k
|
||||
18E+f3WM52I2RssEk6g0X1vIiarHZU5qyxbv2iNoT7EfgizzlXYvx06pM69GNBQr
|
||||
V46+lNhiOv4eeLZcOHBnxAyizlIKyLuwO+C1cX/6BxuXjX3ogw+6IaBFZN/EOMmT
|
||||
Wc6sPKrnNCEqgCNiTbPAXb+N8j5Iv8QPs0AwVTB3jC9LP0mRt2GGD0cu+QIZkoGE
|
||||
hyW9Dd+0tgeIK32uXCF8uDjNpUV1TxCdn5H+lvgddxfiaIJAdY5UaTx48XRIdULh
|
||||
QrVKXJNyTYWTXbezViYIf1nXOdDI2hsGgKTfNVCocDT1LcT5zebijFHVCWfAAKEP
|
||||
RLdzPZomkFIa3rQQgChgePzE8Oqsaxuwx8sU09NAo3giSq1OmBBwly7h60Lwtm8+
|
||||
XuwmWtEgZoSQy2Hm8UMAJ3guotfYuS8mPQBi55JZpdqVN0D5SdwuWXhHpO4xDodN
|
||||
YAoMMei1NNgrX2zN3FCS8PVi97wD6cQ8xsWM62nByrzIjmPwTfoCb3qP/928FMJM
|
||||
g7b3bYBrUnOrpVWZfAIDs4H7DoP8VLL4rMgB5PuWNQ13gtX7y5ZOyLhopiKLnar9
|
||||
XiN8GAMANBdKRI2anGEozrfJoelJ5POXZwSatRjbL+nWO3YnBzEunCw1xmMCAwEA
|
||||
AQKCAgBAYYABP3SW5sPVD+XzjPERiPPNh7P1MdJ5aI7dMFEU6Bt50VkdRRn83d2p
|
||||
v6iTaIXGxNMXiWQxdzusO9FbyeEkMz5F3+i6e2WHpmKUPGvunV/w9aFgibBt1HV2
|
||||
a6fSNpVrCiw758qZaVUi3zZ4V1qa5A2j4EX0IUnSRBIi2ftnCZtg+Zx6JHiGu/Xk
|
||||
KvcfLgtQAO5wOiJrdnt3tgVTHNuSipsvfbw6TmAbbKzNRrPG5xlVQxxVjmypMVMc
|
||||
HJmZdSNSPrwm5JtwXNkTSzAclv6v+XeFdztvJ1pnJ5jO5WAegy8MchNgcfLlWLt7
|
||||
sYlngZQ/1+Q/UHh0GFDQD87yBOmNz8KK5n+5gWB5iumdJ4BHTgUOfXpWilwb0JWG
|
||||
r7ctqCYrbXXTvsIbRl47zGPzEsbs0mSLAuLzZ3IQ60uaYRt322bqzZQNBwJcUXYM
|
||||
lRb6nc9BVAzqhvUemOlACbYlqXENmQy/Nz14nsNdy4Qrynsfon92dRZ0m+9rJ9Hj
|
||||
99K4CNPz0FdayC7jTL76b8QEzoF2MGiKIL5yQYXm9Pt9p0g8g9sER7G7UyrMFqtl
|
||||
tfylkAWRX5hgDCwQQ/Gqefn7xb/kG/4D1FBE5i2yU4tYw5NCzENo8Y3mUhBqiQql
|
||||
G33sSv2JK/woxRWSbyGLfu1Iq2L8H/q4CdN55xat2iKbpL8omQKCAQEA6qX7V8A0
|
||||
uCg0E/Uid6/Xma0dvZ7e5BMKcx0uElSUhUpB6JnEQRlgljRXF/Op8Iae09Gox6bZ
|
||||
nU5Ow61wtSrnJY+f/2RVs9xYB+SSO0L0yE/XPKsBveH0dH9R4BWmH+KZ3sLaYovs
|
||||
ZDsApR782Zh+1TthUT2s4vZ0G25f46xsjKpUzQLmgWeC3UEOThtQo/UZzLeprImI
|
||||
fijMw+5jYUgHSXN80BXO56JzHQJU6SIDmA4BrlD0qPaDyzLVdNhG/nIbYKvf120p
|
||||
ogWqEYIgVN4KyjLsvVgfxCEF4Ucwov9VCNgsVTlEtYWzAXEXqf2AW1j7Sh4GlVOz
|
||||
W4UsfiGaSCjM7wKCAQEA1QuDLQ4cf4UEKsdPOnDYrkHwx6JBBHpkyZZcLhlT/S5A
|
||||
AcvVcEJjeseNfCEexO7SChenlRQEVB8iXO28ZEumWePEz2JK9rq9p7AItk+ba/D9
|
||||
qzfvZ/XE+1xs5szTfwr12Of8b9dXxhoW8gKcFPnKOHxvua6SyocmRlnZtaJRFZ7x
|
||||
RxOZhfWoOUnc+ySYKhKyuipKR4KmyDd2d2ovxptlMFnj2RJzfjUIZiQpKTa8kXf7
|
||||
sYaOgFiNC0AFAs9ZLCEX3NYTKpgVbVKNIaKtNj8GIAG2YPnT/VcbQtj9ULyJcvEw
|
||||
IdzJXn+Cv6ie1nP05P+eo/gtGmm5okXzMQNv0wcFzQKCAQBmDVBWJtMG8P1NXMTj
|
||||
1wdm3+LacHkyKpHV5O//qud5XQVzO0UepwHZ8eObGC9l27bCGyJTyt5ESyV4dztY
|
||||
n9MuA9wrQCEB+6gRrrhmq8U4RXkv+pPkWJxv+lvKoL/CiFQxjP9b8s0Z/otWRTbl
|
||||
ECzBYnT911wUzelLcOKla30+ZGpDS6qixzkkL0IgeELHPDc/UPWrg5lofSgpYsm4
|
||||
KpJ4wJCdE48MMRvtlvEE//UeMaFLhgwSXDyPqIkrq1CdI1WC4t2UnPaJb/s6aCTV
|
||||
pEh/DkzmQKh4LYCYLNUbXv9FvHbzjdezNvXWf7AyD32+vOF1p79nPKL5/96M8OJf
|
||||
1dbjAoIBABKld02yNnxSwBKebyjGR7C4xMI0SUyDCd868cZ3IQq/yYpetMemh95v
|
||||
KMr8exzxaiDIATrjDZ3vO6q2hA6jMGQds1QTXkxJ+995YMnUHd5MsWcS9jk7IYp+
|
||||
hGmO89PiubHKXCXNyzjjf66e29paIoDfI0g1J1PikE8H/i4Pjtk9mBCIfp9i6N5a
|
||||
wKSah1bnXA0/NlEb9kz/zbaV7KiNYUXiGDcfjkw1iA6oi5G34Lk6ryTSihZhqbaa
|
||||
W9XrH/rkypnhgrvvo7B10TRocJCW44pZnATQ2OULgq9PHpy6Y61Tvsq38Ef9EQyF
|
||||
TaGndH+2f8QKLKhrKHwzcx2PF3J44uECggEBAM0UGu/Aj4tIRmrcuPGHypkcxMY6
|
||||
BS2irwiVD9/8Xnx0/r8RSnBuAXEUY8wTrP0GqGm9PZjFCXKyxk3gi6SkahTu6/SF
|
||||
WecgomVnONI+ivpHRLmRXTTPEv7iu1F+2jgVQyg0mOR5WLE0r25S6NS6IlnnrTSo
|
||||
QuIJa1wRIfyXrMpYk77YIOny+mYB4FYr25tChgieQGR4m3dlZICPYqOyFh9GORZ8
|
||||
k1cVboGtKGYtAemzAh/PyUp716tMz44fnnHPzINUFI3ucybqUwpGiR9s0E3L+GsV
|
||||
3h7a2v90RdyWcuAPJL0B5FL5NoHhOMYb1rCMu00FyqCKqXCgte2w2psOP60=
|
||||
MIIJKAIBAAKCAgEA8O2hLVt/7v6rQF2eGX3J+QyteV45lI/5qlyqTe7CiwUg1bkJ
|
||||
2yLHaoGSWoVtthE/X7GZgsw57VEgnazZAeheXcxV8OJWBGuRfmXabtKIzSBF8uZj
|
||||
+H3iPDvJB7NggMh8teYsdBSn9Cm/L5FesDvg/KxUKKfBU4LSrhOMhBauIoOSVU65
|
||||
9y3kYgpzC/ormvCsJSe3KSdIhtLxiv+dnEHh9WvsXWB50lIw3TIC041aL5mwRvb5
|
||||
/JWcjtn5bgLEChrnEGF0RYUDMwm8hT1YsEN9Rb9fOx5ZTUZNRVHYjaCyUA+cG+gC
|
||||
72EjrkXY4If3pAESNcF+5NGGJaETd8rHzHsRFRVPXkwhRmkx9nBF+RjQhouqBTpt
|
||||
IcIO2rPlTC9H5Oeg+jVljlBJ7/ESeOlg2OEbYyOUJpAPMPcz5HiNSTRHuDWIDUuk
|
||||
48BOF9Vo00PJq/oXRzUa9HHhu6cosfZH4P4PkDthxq89migqUL+C8WqeZ8I+xFS8
|
||||
/1TpvjOnOYF5ADvByC69UGPEoh+o+ZpgWfAsCrb9Qwy9WAAZg0rsouoPqb4Qk6Vr
|
||||
88X6I20Ys9AayLzZ72ddoS5IweOoF5/xLfiicGLKckNwG6sy4f1LCFB2Xc79nYqJ
|
||||
zlwPGC3pKfEIAXUj1I/p+/MqaTDJQs72dhr0lTX5505XUBqrbX0BPGcZvIsCAwEA
|
||||
AQKCAgEA7rvJNlSwlHWt4/3gJ4pJlItHajg//kIcNv/TkZ3BEFhojN7qMUZpK9Rw
|
||||
3VnRuNOmZIBriPwtekcldphMAGPs/iz4C9V7Pq4IYaMzqxTbkcclCOfar+StRNpI
|
||||
/WR1f6cqTGRkMDI3qu2jENOPbDopWra4PgDcxI+hi/S7DDgdHP4bBoUYKSJEaBHK
|
||||
plei1ckeC0Mrb5AJge+MgRuBZdCywqnKcUyj6hCfcs+XlWE/uGMmFWutkuf9VmAP
|
||||
lT8QWqMFy2mF+U0wOmavc6eyNhbqDy7ugno0Kyo6bzIGz3AowMR3AAAKyIENBicY
|
||||
HIUeklitXq75umsT7j2KOO2qxag85ycQAC549AGO+OWdig29RjSBniame3w5EjNl
|
||||
sI2L2dms7IvFqkXVUEcytNEZF27Yg/oCh8CWPd5iSaa+/F2mYnXovA03lNrYYLwf
|
||||
lmrOQGEw6gC4Uj9xpf67oRy78rIg1dztEiiqO0yz15z+Kgv7YVF/GnGT7ieqgHrc
|
||||
j4L0vt0nShByzA9k8wpNsgZAPDKvSYIzLwrh/Br96eKg0nysnnJHnvnCjTX0tbUp
|
||||
vlk/YhlGde1/BKnw/6P/lKLqRXkoY3cbQfOinlLIiY6w0TGPdDuSMeHJ9pyftz3S
|
||||
I6Hi9Ty2Y9yYGkCcdWFcnLtQNq4WVwRd7S6wHVHAD1xYc/SRNgECggEBAPzM7+5d
|
||||
sucEpQnRmG+6E+YaYSbzN8ZPK4pC3NID4GlJ/EGCOnewQlaJO4DVJ00h9HnuwRN8
|
||||
X2jm4R5YXXHo+NptxWqYpydz6EvjFU2rJAhdy/qi+yJrKyIcmdUNe3BwvY6A0CW2
|
||||
pkkAou2Yrw2UxnGC20ou7klXf9tx7noSkHtz4uhO2goC3fGr3eN5W+NlbyMOZElE
|
||||
wNqW/cjxYTg9DcImlfC7V9/Ubwwq9te2YAAaGlbcuZHWOpzoCyzrv9g73WTeXSnA
|
||||
WaqjFSCDPQQNvtzckxxlRHkEKomy4inLNDBPf+cRdIuwomHe4KYtbkKCoQ381yg3
|
||||
GjYQ+pJUHWzKz0ECggEBAPP6OgVsxvNuAYv1QQgsfgZE95GW4019bn6cYVFT0eL+
|
||||
jdYr7tXv5DUmNtl4sM49IXNcggfpOEDEWSToMgVP2I14WOrDOIj3+U7EodY/qeVT
|
||||
UjFMTKnA4BXnt5geIE5T8Fgw3XlxHRAgiDWEXht7lU/pk2qHISl/Qf9ZYKpBU4i2
|
||||
USnfHBlzCnZc3lQKkm9QiH4DJLhFfTAZJ1IpN5TH4+h2o+Y6acDlDjQuG1ENFheu
|
||||
+p/+BLtIqDZu1r+AlHIvHUBP7Hw8n///oN8i54fCJZSMv7xCj2E+aaNa55dGjNcp
|
||||
YhkmBPcVZyJapW13/S1OgIQOdx06MmKSVu0a9mbSZMsCggEAPIK1f6Hv+7ox4urH
|
||||
iR7KOo7f6FnZZN94dYzRnHePFMS/29JXOmT3TA1nL8xVrvHMug77KjXgBJUXF5Nh
|
||||
Mq3oOyiBU6WchSYKWXfOlpu7cUE6XRD7+d4bIfwkmkmy3VQvG1gb+psArIK5fRPJ
|
||||
+v88jNkcsmIPaYDHOvjHc3LUIKi5jI+rQzAyffF8mEFpTEHwWzzLpnoNi4UO1DVq
|
||||
5vI+Q9XGmCvPueT4e7ohAbtGuV+GJHqK9KyJtRsZ6bO4ZQLXWJidRiwjimOk3/Zp
|
||||
+Xls0SL/F5Hp1Om5YOJvnj9ki5fL7rxP4Ev0Ymbd8Qj41nS8JkP6IEcoP/7Ka5I0
|
||||
xOC6wQKCAQAi5pWsNv5Szla8Ta4q3Cp+/RipI/uKFzpaNEabmrD4ls91Zr14ryNn
|
||||
EvtfqqsoJYiGdyJGvW8FnNDfvbOCHQTuX9vgYWLR/R8VzH0WJ+9G1d95G+APnH6x
|
||||
w3747L5UVh+YjgzwlWTB7NVvSmsn5Urbrp8e6wusYv7u5zszv7qSYPpFUhwz68gA
|
||||
XJKVVRnTgKK12/9BuPcKjV6ZmznPN7T7iRUzFwIPzPR2NG5F7uhNJQPHJVBJ9j/R
|
||||
4ZMou90AZIr7qzM6JnYA6fF6WgTi37v+fw/if2cBUytLafKdKkN1d/8Hd+/X5KDn
|
||||
Qi5N9Y8rDwLFYUhazvtsLGDw9B1xYgF3AoIBAChp2H++3PAEjJvOj0vjWnkKCfmz
|
||||
CZim1+SxobQTGEWeQJavRbsZAyVE2OeP7N58Rw2VeihS5qm3jxs9J7Xv0Fnq4zDn
|
||||
T4bHx2PgmdDoJpMlC1f08KtEovBc1W89x+IY6MYlPO7I9nKBMK2b9yWaI7GF1aQv
|
||||
dvfWhJZdmia0Tp0a8CZ8/LD4qmWztB1KIkbkqayPmFVVHtbJ3+XfIrTTDU6T1Tsf
|
||||
59vzFYXCFkjwtBm9OOpm4TSRsDN5iKZAjdSCHwoJilD+y7IqT/0WDAoTtgAPRJaU
|
||||
u10OOOy/GAuCtNRYLQ5EfXHYLtE06lsMRCHNgsxCtPlULiChbiSnTq0CBbc=
|
||||
-----END rsa private key-----
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
-----BEGIN rsa public key-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw0anfgtraA2uaZwoLpLB
|
||||
vo1EkfYvDBgeXoMQ4WMKbcw6jU8k18E+f3WM52I2RssEk6g0X1vIiarHZU5qyxbv
|
||||
2iNoT7EfgizzlXYvx06pM69GNBQrV46+lNhiOv4eeLZcOHBnxAyizlIKyLuwO+C1
|
||||
cX/6BxuXjX3ogw+6IaBFZN/EOMmTWc6sPKrnNCEqgCNiTbPAXb+N8j5Iv8QPs0Aw
|
||||
VTB3jC9LP0mRt2GGD0cu+QIZkoGEhyW9Dd+0tgeIK32uXCF8uDjNpUV1TxCdn5H+
|
||||
lvgddxfiaIJAdY5UaTx48XRIdULhQrVKXJNyTYWTXbezViYIf1nXOdDI2hsGgKTf
|
||||
NVCocDT1LcT5zebijFHVCWfAAKEPRLdzPZomkFIa3rQQgChgePzE8Oqsaxuwx8sU
|
||||
09NAo3giSq1OmBBwly7h60Lwtm8+XuwmWtEgZoSQy2Hm8UMAJ3guotfYuS8mPQBi
|
||||
55JZpdqVN0D5SdwuWXhHpO4xDodNYAoMMei1NNgrX2zN3FCS8PVi97wD6cQ8xsWM
|
||||
62nByrzIjmPwTfoCb3qP/928FMJMg7b3bYBrUnOrpVWZfAIDs4H7DoP8VLL4rMgB
|
||||
5PuWNQ13gtX7y5ZOyLhopiKLnar9XiN8GAMANBdKRI2anGEozrfJoelJ5POXZwSa
|
||||
tRjbL+nWO3YnBzEunCw1xmMCAwEAAQ==
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA8O2hLVt/7v6rQF2eGX3J
|
||||
+QyteV45lI/5qlyqTe7CiwUg1bkJ2yLHaoGSWoVtthE/X7GZgsw57VEgnazZAehe
|
||||
XcxV8OJWBGuRfmXabtKIzSBF8uZj+H3iPDvJB7NggMh8teYsdBSn9Cm/L5FesDvg
|
||||
/KxUKKfBU4LSrhOMhBauIoOSVU659y3kYgpzC/ormvCsJSe3KSdIhtLxiv+dnEHh
|
||||
9WvsXWB50lIw3TIC041aL5mwRvb5/JWcjtn5bgLEChrnEGF0RYUDMwm8hT1YsEN9
|
||||
Rb9fOx5ZTUZNRVHYjaCyUA+cG+gC72EjrkXY4If3pAESNcF+5NGGJaETd8rHzHsR
|
||||
FRVPXkwhRmkx9nBF+RjQhouqBTptIcIO2rPlTC9H5Oeg+jVljlBJ7/ESeOlg2OEb
|
||||
YyOUJpAPMPcz5HiNSTRHuDWIDUuk48BOF9Vo00PJq/oXRzUa9HHhu6cosfZH4P4P
|
||||
kDthxq89migqUL+C8WqeZ8I+xFS8/1TpvjOnOYF5ADvByC69UGPEoh+o+ZpgWfAs
|
||||
Crb9Qwy9WAAZg0rsouoPqb4Qk6Vr88X6I20Ys9AayLzZ72ddoS5IweOoF5/xLfii
|
||||
cGLKckNwG6sy4f1LCFB2Xc79nYqJzlwPGC3pKfEIAXUj1I/p+/MqaTDJQs72dhr0
|
||||
lTX5505XUBqrbX0BPGcZvIsCAwEAAQ==
|
||||
-----END rsa public key-----
|
||||
|
||||
@@ -620,7 +620,7 @@ func main() {
|
||||
|
||||
### <span id="Nand">Nand</span>
|
||||
|
||||
<p>Returns a composed predicate that represents the logical NAND of a list of predicates. It evaluates to true only if all predicates evaluate to false for the given value.</p>
|
||||
<p>Returns a composed predicate that represents the logical NAND of a list of predicates. It evaluates to false only if all predicates evaluate to true for the given value.</p>
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
@@ -650,7 +650,7 @@ func main() {
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
```
|
||||
|
||||
@@ -18,7 +18,7 @@ func And[T any](predicates ...func(T) bool) func(T) bool {
|
||||
}
|
||||
|
||||
// Nand returns a composed predicate that represents the logical NAND of a list of predicates.
|
||||
// It evaluates to true only if all predicates evaluate to false for the given value.
|
||||
// It evaluates to false only if all predicates evaluate to true for the given value.
|
||||
// Play: https://go.dev/play/p/Rb-FdNGpgSO
|
||||
func Nand[T any](predicates ...func(T) bool) func(T) bool {
|
||||
if len(predicates) < 2 {
|
||||
@@ -26,11 +26,11 @@ func Nand[T any](predicates ...func(T) bool) func(T) bool {
|
||||
}
|
||||
return func(value T) bool {
|
||||
for _, predicate := range predicates {
|
||||
if predicate(value) {
|
||||
return false // Short-circuit on the first true predicate
|
||||
if !predicate(value) {
|
||||
return true // Short-circuit on the first false predicate
|
||||
}
|
||||
}
|
||||
return true // True if all predicates are false
|
||||
return false // False if all predicates are true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ func ExampleNand() {
|
||||
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ func TestPredicatesNandPure(t *testing.T) {
|
||||
)
|
||||
|
||||
assert.ShouldBeFalse(isNumericAndLength5("12345"))
|
||||
assert.ShouldBeFalse(isNumericAndLength5("1234"))
|
||||
assert.ShouldBeTrue(isNumericAndLength5("1234"))
|
||||
assert.ShouldBeTrue(isNumericAndLength5("abcdef"))
|
||||
}
|
||||
|
||||
|
||||
@@ -507,19 +507,17 @@ func flattenRecursive(value reflect.Value, result reflect.Value) reflect.Value {
|
||||
}
|
||||
|
||||
// ForEach iterates over elements of slice and invokes function for each element.
|
||||
// Play: https://go.dev/play/p/DrPaa4YsHRF
|
||||
func ForEach[T any](slice []T, iteratee func(index int, item T)) {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
iteratee(i, slice[i])
|
||||
for idx, elem := range slice {
|
||||
iteratee(idx, elem)
|
||||
}
|
||||
}
|
||||
|
||||
// ForEachWithBreak iterates over elements of slice and invokes function for each element,
|
||||
// when iteratee return false, will break the for each loop.
|
||||
// Play: https://go.dev/play/p/qScs39f3D9W
|
||||
// when function return false, will break the for each loop.
|
||||
func ForEachWithBreak[T any](slice []T, iteratee func(index int, item T) bool) {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
if !iteratee(i, slice[i]) {
|
||||
for idx, elem := range slice {
|
||||
if !iteratee(idx, elem) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -1465,36 +1463,28 @@ func Random[T any](slice []T) (val T, idx int) {
|
||||
return slice[idx], idx
|
||||
}
|
||||
|
||||
// RightPadding adds padding to the right end of a slice.
|
||||
// RightPadding returns a copy of the slice padding the given value to the right end of a slice.
|
||||
// If paddingLength is zero or less, the function returns a copy of the slice.
|
||||
// Play: https://go.dev/play/p/0_2rlLEMBXL
|
||||
func RightPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
||||
if paddingLength == 0 {
|
||||
return slice
|
||||
suffix := []T{}
|
||||
if paddingLength > 0 {
|
||||
suffix = repeat([]T{paddingValue}, paddingLength)
|
||||
}
|
||||
for i := 0; i < paddingLength; i++ {
|
||||
slice = append(slice, paddingValue)
|
||||
}
|
||||
return slice
|
||||
padded := concat(slice, suffix)
|
||||
return padded
|
||||
}
|
||||
|
||||
// LeftPadding adds padding to the left begin of a slice.
|
||||
// LeftPadding returns a copy of the slice padding the given value to the left begin of a slice.
|
||||
// If paddingLength is zero or less, the function returns a copy of the slice.
|
||||
// Play: https://go.dev/play/p/jlQVoelLl2k
|
||||
func LeftPadding[T any](slice []T, paddingValue T, paddingLength int) []T {
|
||||
if paddingLength == 0 {
|
||||
return slice
|
||||
prefix := []T{}
|
||||
if paddingLength > 0 {
|
||||
prefix = repeat([]T{paddingValue}, paddingLength)
|
||||
}
|
||||
|
||||
paddedSlice := make([]T, len(slice)+paddingLength)
|
||||
i := 0
|
||||
for ; i < paddingLength; i++ {
|
||||
paddedSlice[i] = paddingValue
|
||||
}
|
||||
for j := 0; j < len(slice); j++ {
|
||||
paddedSlice[i] = slice[j]
|
||||
i++
|
||||
}
|
||||
|
||||
return paddedSlice
|
||||
padded := concat(prefix, slice)
|
||||
return padded
|
||||
}
|
||||
|
||||
// Frequency counts the frequency of each element in the slice.
|
||||
|
||||
@@ -831,7 +831,7 @@ func ExampleUniqueByComparator() {
|
||||
})
|
||||
|
||||
caseInsensitiveStrings := UniqueByComparator([]string{"apple", "banana", "Apple", "cherry", "Banana", "date"}, func(item string, other string) bool {
|
||||
return strings.ToLower(item) == strings.ToLower(other)
|
||||
return strings.EqualFold(item, other)
|
||||
})
|
||||
|
||||
fmt.Println(uniqueNums)
|
||||
|
||||
@@ -2,6 +2,7 @@ package slice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
@@ -96,3 +97,71 @@ func partitionAnySlice[T any](slice []T, lowIndex, highIndex int, less func(a, b
|
||||
func swap[T any](slice []T, i, j int) {
|
||||
slice[i], slice[j] = slice[j], slice[i]
|
||||
}
|
||||
|
||||
// `repeat` returns a new slice that repeats the provided slice the given number of
|
||||
// times. The result has length and capacity (len(x) * count). The result is never nil.
|
||||
// Repeat panics if count is negative or if the result of (len(x) * count) overflows.
|
||||
//
|
||||
// repeat has been provided in the standard lib within the package `slices` under the
|
||||
// name Repeat since GO version 1.21 onwards. As lancet commits to compatibility with GO
|
||||
// 1.18 onwards, we implement the functionality as an internal function.
|
||||
func repeat[S ~[]E, E any](x S, count int) S {
|
||||
if count < 0 {
|
||||
panic("count cannot be negative")
|
||||
}
|
||||
|
||||
const maxInt = ^uint(0) >> 1
|
||||
hi, lo := bits.Mul(uint(len(x)), uint(count))
|
||||
if hi > 0 || lo > maxInt {
|
||||
panic("the result of (len(x) * count) overflows")
|
||||
}
|
||||
|
||||
newslice := make(S, int(lo)) // lo = len(x) * count
|
||||
n := copy(newslice, x)
|
||||
for n < len(newslice) {
|
||||
n += copy(newslice[n:], newslice[:n])
|
||||
}
|
||||
return newslice
|
||||
}
|
||||
|
||||
// concat returns a new slice concatenating the passed in slices.
|
||||
//
|
||||
// concat has been provided in the standard lib within the package `slices` under the
|
||||
// name Concat since GO version 1.21 onwards. As lancet commits to compatibility with GO
|
||||
// 1.18 onwards, we implement the functionality as an internal function.
|
||||
func concat[S ~[]E, E any](slices ...S) S {
|
||||
size := 0
|
||||
for _, s := range slices {
|
||||
size += len(s)
|
||||
if size < 0 {
|
||||
panic("len out of range")
|
||||
}
|
||||
}
|
||||
// Use Grow, not make, to round up to the size class:
|
||||
// the extra space is otherwise unused and helps
|
||||
// callers that append a few elements to the result.
|
||||
newslice := grow[S](nil, size)
|
||||
for _, s := range slices {
|
||||
newslice = append(newslice, s...)
|
||||
}
|
||||
return newslice
|
||||
}
|
||||
|
||||
// grow increases the slice's capacity, if necessary, to guarantee space for
|
||||
// another n elements. After grow(n), at least n elements can be appended
|
||||
// to the slice without another allocation. If n is negative or too large to
|
||||
// allocate the memory, grow panics.
|
||||
//
|
||||
// grow has been provided in the standard lib within the package `slices` under the
|
||||
// name Grow since GO version 1.21 onwards. As lancet commits to compatibility with GO
|
||||
// 1.18 onwards, we implement the functionality as an internal function.
|
||||
func grow[S ~[]E, E any](s S, n int) S {
|
||||
if n < 0 {
|
||||
panic("cannot be negative")
|
||||
}
|
||||
if n -= cap(s) - len(s); n > 0 {
|
||||
// This expression allocates only once.
|
||||
s = append(s[:cap(s)], make([]E, n)...)[:len(s)]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -1008,7 +1008,7 @@ func TestUniqueByComparator(t *testing.T) {
|
||||
t.Run("case-insensitive string comparison", func(t *testing.T) {
|
||||
stringSlice := []string{"apple", "banana", "Apple", "cherry", "Banana", "date"}
|
||||
caseInsensitiveComparator := func(item, other string) bool {
|
||||
return strings.ToLower(item) == strings.ToLower(other)
|
||||
return strings.EqualFold(item, other)
|
||||
}
|
||||
|
||||
result := UniqueByComparator(stringSlice, caseInsensitiveComparator)
|
||||
@@ -1756,6 +1756,20 @@ func TestRightPaddingAndLeftPadding(t *testing.T) {
|
||||
|
||||
padded := LeftPadding(RightPadding(nums, 0, 3), 0, 3)
|
||||
assert.Equal([]int{0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0}, padded)
|
||||
|
||||
// Test with negative padding length
|
||||
paddedNegative := LeftPadding(RightPadding(nums, 0, -3), 0, -3)
|
||||
assert.Equal([]int{1, 2, 3, 4, 5}, paddedNegative)
|
||||
|
||||
// Test with empty slice
|
||||
empty := []int{}
|
||||
paddedEmpty := LeftPadding(RightPadding(empty, 0, 3), 0, 3)
|
||||
assert.Equal([]int{0, 0, 0, 0, 0, 0}, paddedEmpty)
|
||||
|
||||
// Test with nil
|
||||
nilSlice := []int(nil)
|
||||
paddedNil := LeftPadding(RightPadding(nilSlice, 0, 3), 0, 3)
|
||||
assert.Equal([]int{0, 0, 0, 0, 0, 0}, paddedNil)
|
||||
}
|
||||
|
||||
func TestUniqueByConcurrent(t *testing.T) {
|
||||
|
||||
@@ -39,10 +39,26 @@ var (
|
||||
visaMatcher *regexp.Regexp = regexp.MustCompile(`^4[0-9]{12}(?:[0-9]{3})?$`)
|
||||
masterCardMatcher *regexp.Regexp = regexp.MustCompile(`^5[1-5][0-9]{14}$`)
|
||||
americanExpressMatcher *regexp.Regexp = regexp.MustCompile(`^3[47][0-9]{13}$`)
|
||||
unionPay *regexp.Regexp = regexp.MustCompile("^62[0-5]\\d{13,16}$")
|
||||
chinaUnionPay *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
|
||||
unionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-5]\\d{13,16}$`)
|
||||
chinaUnionPayMatcher *regexp.Regexp = regexp.MustCompile(`^62[0-9]{14,17}$`)
|
||||
)
|
||||
|
||||
var passportMatcher = map[string]*regexp.Regexp{
|
||||
"CN": regexp.MustCompile(`^P\d{9}$`),
|
||||
"US": regexp.MustCompile(`^\d{9}$`),
|
||||
"GB": regexp.MustCompile(`^[A-Z0-9]{9}$`),
|
||||
"RU": regexp.MustCompile(`^[A-Z]{2}\d{7}$`),
|
||||
"DE": regexp.MustCompile(`^\d{9}$`),
|
||||
"FR": regexp.MustCompile(`^[A-Z]{2}\d{7}$`),
|
||||
"JP": regexp.MustCompile(`^\d{8}$`),
|
||||
"IT": regexp.MustCompile(`^\d{8}$`),
|
||||
"AU": regexp.MustCompile(`^[A-Z]{1}\d{8}$`),
|
||||
"BR": regexp.MustCompile(`^\d{9}$`),
|
||||
"IN": regexp.MustCompile(`^[A-Z]{1,2}\d{7}$`),
|
||||
"HK": regexp.MustCompile(`^M\d{8}$`),
|
||||
"MO": regexp.MustCompile(`^[A-Z]\d{8}$`),
|
||||
}
|
||||
|
||||
var (
|
||||
// Identity card formula
|
||||
factor = [17]int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
||||
@@ -460,12 +476,13 @@ func IsZeroValue(value any) bool {
|
||||
func IsGBK(data []byte) bool {
|
||||
i := 0
|
||||
for i < len(data) {
|
||||
if data[i] <= 0xff {
|
||||
if data[i] < 0x81 {
|
||||
i++
|
||||
continue
|
||||
} else {
|
||||
if data[i] >= 0x81 &&
|
||||
data[i] <= 0xfe &&
|
||||
i+1 < len(data) &&
|
||||
data[i+1] >= 0x40 &&
|
||||
data[i+1] <= 0xfe &&
|
||||
data[i+1] != 0xf7 {
|
||||
@@ -562,11 +579,22 @@ func IsAmericanExpress(v string) bool {
|
||||
// IsUnionPay check if a give string is a valid union pay nubmer or not.
|
||||
// Play: https://go.dev/play/p/CUHPEwEITDf
|
||||
func IsUnionPay(v string) bool {
|
||||
return unionPay.MatchString(v)
|
||||
return unionPayMatcher.MatchString(v)
|
||||
}
|
||||
|
||||
// IsChinaUnionPay check if a give string is a valid china union pay nubmer or not.
|
||||
// Play: https://go.dev/play/p/yafpdxLiymu
|
||||
func IsChinaUnionPay(v string) bool {
|
||||
return chinaUnionPay.MatchString(v)
|
||||
return chinaUnionPayMatcher.MatchString(v)
|
||||
}
|
||||
|
||||
// IsPassport checks if the passport number is valid for a given country.
|
||||
// country is a two-letter country code (ISO 3166-1 alpha-2).
|
||||
// Play: todo
|
||||
func IsPassport(passport, country string) bool {
|
||||
if matcher, ok := passportMatcher[country]; ok {
|
||||
return matcher.MatchString(passport)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -683,3 +683,21 @@ func ExampleIsAlphaNumeric() {
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleIsPassport() {
|
||||
result1 := IsPassport("P123456789", "CN")
|
||||
result2 := IsPassport("123456789", "US")
|
||||
result3 := IsPassport("AB1234567", "RU")
|
||||
result4 := IsPassport("123456789", "CN")
|
||||
|
||||
fmt.Println(result1)
|
||||
fmt.Println(result2)
|
||||
fmt.Println(result3)
|
||||
fmt.Println(result4)
|
||||
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
@@ -924,3 +924,33 @@ func TestIsAlphaNumeric(t *testing.T) {
|
||||
assert.Equal(tt.expected, IsAlphaNumeric(tt.input))
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsPassport(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestIsPassport")
|
||||
|
||||
tests := []struct {
|
||||
passport string
|
||||
countryCode string
|
||||
expected bool
|
||||
}{
|
||||
{"P123456789", "CN", true},
|
||||
{"123456789", "US", true},
|
||||
{"A12345678", "GB", true},
|
||||
{"AB1234567", "FR", true},
|
||||
{"12345678", "JP", true},
|
||||
{"M12345678", "HK", true},
|
||||
{"A12345678", "MO", true},
|
||||
{"A1234567", "IN", true},
|
||||
{"12345678", "IT", true},
|
||||
{"A12345678", "AU", true},
|
||||
{"123456789", "BR", true},
|
||||
{"AB1234567", "RU", true},
|
||||
{"123456789", "CN", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
assert.Equal(tt.expected, IsPassport(tt.passport, tt.countryCode))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user