2021-01-19 09:59:04 +08:00
|
|
|
|
package utils
|
|
|
|
|
|
|
|
|
|
import (
|
2022-12-16 23:34:14 +08:00
|
|
|
|
"crypto/rand"
|
|
|
|
|
"math/big"
|
2021-01-28 23:19:59 +08:00
|
|
|
|
"os"
|
2021-05-27 20:48:12 +08:00
|
|
|
|
"regexp"
|
2024-10-21 12:11:02 +08:00
|
|
|
|
"strconv"
|
2022-05-17 20:16:46 +08:00
|
|
|
|
"strings"
|
2022-03-18 23:13:22 +08:00
|
|
|
|
|
2024-10-21 12:11:02 +08:00
|
|
|
|
"golang.org/x/exp/constraints"
|
|
|
|
|
|
2022-03-18 23:13:22 +08:00
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
2021-01-19 09:59:04 +08:00
|
|
|
|
)
|
|
|
|
|
|
2024-10-17 21:03:03 +08:00
|
|
|
|
var (
|
|
|
|
|
Json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
|
|
|
|
2024-10-18 22:06:01 +08:00
|
|
|
|
DNSServers = []string{"1.1.1.1:53", "223.5.5.5:53"}
|
2024-10-17 21:03:03 +08:00
|
|
|
|
)
|
2022-03-18 23:13:22 +08:00
|
|
|
|
|
2021-05-27 20:48:12 +08:00
|
|
|
|
var ipv4Re = regexp.MustCompile(`(\d*\.).*(\.\d*)`)
|
|
|
|
|
|
|
|
|
|
func ipv4Desensitize(ipv4Addr string) string {
|
|
|
|
|
return ipv4Re.ReplaceAllString(ipv4Addr, "$1****$2")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ipv6Re = regexp.MustCompile(`(\w*:\w*:).*(:\w*:\w*)`)
|
|
|
|
|
|
|
|
|
|
func ipv6Desensitize(ipv6Addr string) string {
|
|
|
|
|
return ipv6Re.ReplaceAllString(ipv6Addr, "$1****$2")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IPDesensitize(ipAddr string) string {
|
|
|
|
|
ipAddr = ipv4Desensitize(ipAddr)
|
|
|
|
|
ipAddr = ipv6Desensitize(ipAddr)
|
|
|
|
|
return ipAddr
|
|
|
|
|
}
|
2022-05-17 20:16:46 +08:00
|
|
|
|
|
|
|
|
|
// SplitIPAddr 传入/分割的v4v6混合地址,返回v4和v6地址与有效地址
|
|
|
|
|
func SplitIPAddr(v4v6Bundle string) (string, string, string) {
|
|
|
|
|
ipList := strings.Split(v4v6Bundle, "/")
|
|
|
|
|
ipv4 := ""
|
|
|
|
|
ipv6 := ""
|
|
|
|
|
validIP := ""
|
|
|
|
|
if len(ipList) > 1 {
|
|
|
|
|
// 双栈
|
|
|
|
|
ipv4 = ipList[0]
|
|
|
|
|
ipv6 = ipList[1]
|
|
|
|
|
validIP = ipv4
|
|
|
|
|
} else if len(ipList) == 1 {
|
|
|
|
|
// 仅ipv4|ipv6
|
|
|
|
|
if strings.Contains(ipList[0], ":") {
|
|
|
|
|
ipv6 = ipList[0]
|
|
|
|
|
validIP = ipv6
|
|
|
|
|
} else {
|
|
|
|
|
ipv4 = ipList[0]
|
|
|
|
|
validIP = ipv4
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ipv4, ipv6, validIP
|
|
|
|
|
}
|
2022-06-03 09:45:11 +08:00
|
|
|
|
|
2022-06-24 20:43:38 +08:00
|
|
|
|
func IsFileExists(path string) bool {
|
|
|
|
|
_, err := os.Stat(path)
|
|
|
|
|
return err == nil
|
2022-06-03 09:45:11 +08:00
|
|
|
|
}
|
2022-12-16 23:34:14 +08:00
|
|
|
|
|
|
|
|
|
func GenerateRandomString(n int) (string, error) {
|
|
|
|
|
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
|
|
|
lettersLength := big.NewInt(int64(len(letters)))
|
|
|
|
|
ret := make([]byte, n)
|
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
|
num, err := rand.Int(rand.Reader, lettersLength)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
ret[i] = letters[num.Int64()]
|
|
|
|
|
}
|
|
|
|
|
return string(ret), nil
|
|
|
|
|
}
|
2024-08-11 10:35:19 +08:00
|
|
|
|
|
|
|
|
|
func Uint64SubInt64(a uint64, b int64) uint64 {
|
|
|
|
|
if b < 0 {
|
|
|
|
|
return a + uint64(-b)
|
|
|
|
|
}
|
2024-08-12 10:06:55 +08:00
|
|
|
|
if a < uint64(b) {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
2024-08-11 10:35:19 +08:00
|
|
|
|
return a - uint64(b)
|
|
|
|
|
}
|
2024-10-20 23:23:04 +08:00
|
|
|
|
|
|
|
|
|
func IfOr[T any](a bool, x, y T) T {
|
|
|
|
|
if a {
|
|
|
|
|
return x
|
|
|
|
|
}
|
|
|
|
|
return y
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IfOrFn[T any](a bool, x, y func() T) T {
|
|
|
|
|
if a {
|
|
|
|
|
return x()
|
|
|
|
|
}
|
|
|
|
|
return y()
|
|
|
|
|
}
|
2024-10-21 12:11:02 +08:00
|
|
|
|
|
|
|
|
|
func Itoa[T constraints.Integer](i T) string {
|
|
|
|
|
switch any(i).(type) {
|
|
|
|
|
case int, int8, int16, int32, int64:
|
|
|
|
|
return strconv.FormatInt(int64(i), 10)
|
|
|
|
|
case uint, uint8, uint16, uint32, uint64:
|
|
|
|
|
return strconv.FormatUint(uint64(i), 10)
|
|
|
|
|
default:
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-23 01:13:39 +08:00
|
|
|
|
|
|
|
|
|
// From go1.23
|
|
|
|
|
|
|
|
|
|
// Compare returns
|
|
|
|
|
//
|
|
|
|
|
// -1 if x is less than y,
|
|
|
|
|
// 0 if x equals y,
|
|
|
|
|
// +1 if x is greater than y.
|
|
|
|
|
//
|
|
|
|
|
// For floating-point types, a NaN is considered less than any non-NaN,
|
|
|
|
|
// a NaN is considered equal to a NaN, and -0.0 is equal to 0.0.
|
|
|
|
|
func Compare[T constraints.Ordered](x, y T) int {
|
|
|
|
|
xNaN := isNaN(x)
|
|
|
|
|
yNaN := isNaN(y)
|
|
|
|
|
if xNaN {
|
|
|
|
|
if yNaN {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
if yNaN {
|
|
|
|
|
return +1
|
|
|
|
|
}
|
|
|
|
|
if x < y {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
if x > y {
|
|
|
|
|
return +1
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// isNaN reports whether x is a NaN without requiring the math package.
|
|
|
|
|
// This will always return false if T is not floating-point.
|
|
|
|
|
func isNaN[T constraints.Ordered](x T) bool {
|
|
|
|
|
return x != x
|
|
|
|
|
}
|