1 Star 0 Fork 0

余济舟/util

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
types.go 13.97 KB
一键复制 编辑 原始数据 按行查看 历史
jericho 提交于 2024-10-12 11:18 . [optimize]增加时间戳微秒级
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
package common
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"reflect"
"strconv"
"strings"
"time"
)
var (
emptyStringMap = map[string]struct{}{
"": {},
"0": {},
"no": {},
"off": {},
"false": {},
}
)
type iVal interface {
Val() any
}
// iString is used for type assert api for String().
type iString interface {
String() string
}
// iBool is used for type assert api for Bool().
type iBool interface {
Bool() bool
}
// iInt64 is used for type assert api for Int64().
type iInt64 interface {
Int64() int64
}
// iUint64 is used for type assert api for Uint64().
type iUint64 interface {
Uint64() uint64
}
// iFloat32 is used for type assert api for Float32().
type iFloat32 interface {
Float32() float32
}
// iFloat64 is used for type assert api for Float64().
type iFloat64 interface {
Float64() float64
}
// iError is used for type assert api for Error().
type iError interface {
Error() string
}
// iBytes is used for type assert api for Bytes().
type iBytes interface {
Bytes() []byte
}
// iInterface is used for type assert api for Interface().
type iInterface interface {
Interface() any
}
// iInterfaces is used for type assert api for Interfaces().
type iInterfaces interface {
Interfaces() []any
}
// iFloats is used for type assert api for Floats().
type iFloats interface {
Floats() []float64
}
// iInts is used for type assert api for Ints().
type iInts interface {
Ints() []int
}
// iStrings is used for type assert api for Strings().
type iStrings interface {
Strings() []string
}
// iUints is used for type assert api for Uints().
type iUints interface {
Uints() []uint
}
// iMapStrAny is the interface support for converting struct parameter to map.
type iMapStrAny interface {
MapStrAny() map[string]any
}
// iUnmarshalValue is the interface for custom defined types customizing value assignment.
// Note that only pointer can implement interface iUnmarshalValue.
type iUnmarshalValue interface {
UnmarshalValue(any) error
}
// iUnmarshalText is the interface for custom defined types customizing value assignment.
// Note that only pointer can implement interface iUnmarshalText.
type iUnmarshalText interface {
UnmarshalText(text []byte) error
}
// iUnmarshalText is the interface for custom defined types customizing value assignment.
// Note that only pointer can implement interface iUnmarshalJSON.
type iUnmarshalJSON interface {
UnmarshalJSON(b []byte) error
}
// iSet is the interface for custom value assignment.
type iSet interface {
Set(value any) (old any)
}
func ToBytes(original any) []byte {
if original == nil {
return nil
}
switch value := original.(type) {
case string:
return []byte(value)
case []byte:
return value
default:
if f, ok := value.(iBytes); ok {
return f.Bytes()
}
refType := reflect.TypeOf(original)
refValue := reflect.ValueOf(original)
switch refType.Kind() {
case reflect.Map:
bytes, err := json.Marshal(original)
if err != nil {
panic(err)
}
return bytes
case reflect.Array, reflect.Slice:
var (
ok = true
bytes = make([]byte, refValue.Len())
)
for i := range bytes {
int32Value := ToInt32(refValue.Index(i).Interface())
if int32Value < 0 || int32Value > math.MaxUint8 {
ok = false
break
}
bytes[i] = byte(int32Value)
}
if ok {
return bytes
}
}
return LeEncode(original)
}
}
func ToInt(original any) int {
if original == nil {
return 0
}
if v, ok := original.(int); ok {
return v
}
return int(ToInt64(original))
}
func ToInt32(original any) int32 {
if original == nil {
return 0
}
if v, ok := original.(int32); ok {
return v
}
return int32(ToInt64(original))
}
func ToInt64(original any) int64 {
if original == nil {
return 0
}
switch value := original.(type) {
case int:
return int64(value)
case int8:
return int64(value)
case int16:
return int64(value)
case int32:
return int64(value)
case int64:
return value
case uint:
return int64(value)
case uint8:
return int64(value)
case uint16:
return int64(value)
case uint32:
return int64(value)
case uint64:
return int64(value)
case float32:
return int64(value)
case float64:
return int64(value)
case bool:
if value {
return 1
}
return 0
case []byte:
return LeDecodeToInt64(value)
default:
if f, ok := value.(iInt64); ok {
return f.Int64()
}
var (
s = ToString(value)
isMinus = false
)
if len(s) > 0 {
if s[0] == '-' {
isMinus = true
s = s[1:]
} else if s[0] == '+' {
s = s[1:]
}
}
// Hexadecimal
if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') {
if v, e := strconv.ParseInt(s[2:], 16, 64); e == nil {
if isMinus {
return -v
}
return v
}
}
// Decimal
if v, e := strconv.ParseInt(s, 10, 64); e == nil {
if isMinus {
return -v
}
return v
}
// Float64
if valueInt64 := ToFloat64(value); math.IsNaN(valueInt64) {
return 0
} else {
return int64(valueInt64)
}
}
}
func ToDatetimeUnixMilli(original any) time.Time {
return time.UnixMilli(ToInt64(original))
}
// Float32 converts `any` to float32.
func ToFloat32(original any) float32 {
if original == nil {
return 0
}
switch value := original.(type) {
case float32:
return value
case float64:
return float32(value)
case []byte:
return LeDecodeToFloat32(value)
default:
if f, ok := value.(iFloat32); ok {
return f.Float32()
}
v, _ := strconv.ParseFloat(ToString(original), 64)
return float32(v)
}
}
// Float64 converts `any` to float64.
func ToFloat64(original any) float64 {
if original == nil {
return 0
}
switch value := original.(type) {
case float32:
return float64(value)
case float64:
return value
case []byte:
return LeDecodeToFloat64(value)
default:
if f, ok := value.(iFloat64); ok {
return f.Float64()
}
v, _ := strconv.ParseFloat(ToString(original), 64)
return v
}
}
func ToString(original any) string {
if original == nil {
return ""
}
switch value := original.(type) {
case int:
return strconv.Itoa(value)
case int8:
return strconv.Itoa(int(value))
case int16:
return strconv.Itoa(int(value))
case int32:
return strconv.Itoa(int(value))
case int64:
return strconv.FormatInt(value, 10)
case uint:
return strconv.FormatUint(uint64(value), 10)
case uint8:
return strconv.FormatUint(uint64(value), 10)
case uint16:
return strconv.FormatUint(uint64(value), 10)
case uint32:
return strconv.FormatUint(uint64(value), 10)
case uint64:
return strconv.FormatUint(value, 10)
case float32:
return strconv.FormatFloat(float64(value), 'f', -1, 32)
case float64:
return strconv.FormatFloat(value, 'f', -1, 64)
case bool:
return strconv.FormatBool(value)
case string:
return value
case []byte:
return string(value)
case time.Time:
if value.IsZero() {
return ""
}
return value.String()
case *time.Time:
if value == nil {
return ""
}
return value.String()
default:
// Empty checks.
if value == nil {
return ""
}
if f, ok := value.(iString); ok {
// If the variable implements the String() interface,
// then use that interface to perform the conversion
return f.String()
}
if f, ok := value.(iError); ok {
// If the variable implements the Error() interface,
// then use that interface to perform the conversion
return f.Error()
}
// Reflection checks.
var (
rv = reflect.ValueOf(value)
kind = rv.Kind()
)
switch kind {
case reflect.Chan,
reflect.Map,
reflect.Slice,
reflect.Func,
reflect.Ptr,
reflect.Interface,
reflect.UnsafePointer:
if rv.IsNil() {
return ""
}
case reflect.String:
return rv.String()
}
if kind == reflect.Ptr {
return ToString(rv.Elem().Interface())
}
// Finally, we use json.Marshal to convert.
if jsonContent, err := json.Marshal(value); err != nil {
return fmt.Sprint(value)
} else {
return string(jsonContent)
}
}
}
func ToBool(original any) bool {
if original == nil {
return false
}
switch value := original.(type) {
case bool:
return value
case []byte:
if _, ok := emptyStringMap[strings.ToLower(string(value))]; ok {
return false
}
return true
case string:
if _, ok := emptyStringMap[strings.ToLower(value)]; ok {
return false
}
return true
default:
if f, ok := value.(iBool); ok {
return f.Bool()
}
rv := reflect.ValueOf(original)
switch rv.Kind() {
case reflect.Ptr:
return !rv.IsNil()
case reflect.Map:
fallthrough
case reflect.Array:
fallthrough
case reflect.Slice:
return rv.Len() != 0
case reflect.Struct:
return true
default:
s := strings.ToLower(ToString(original))
if _, ok := emptyStringMap[s]; ok {
return false
}
return true
}
}
}
func LeEncode(values ...any) []byte {
buf := new(bytes.Buffer)
for i := 0; i < len(values); i++ {
if values[i] == nil {
return buf.Bytes()
}
switch value := values[i].(type) {
case int:
buf.Write(LeEncodeInt(value))
case int8:
buf.Write(LeEncodeInt8(value))
case int16:
buf.Write(LeEncodeInt16(value))
case int32:
buf.Write(LeEncodeInt32(value))
case int64:
buf.Write(LeEncodeInt64(value))
case uint:
buf.Write(LeEncodeUint(value))
case uint8:
buf.Write(LeEncodeUint8(value))
case uint16:
buf.Write(LeEncodeUint16(value))
case uint32:
buf.Write(LeEncodeUint32(value))
case uint64:
buf.Write(LeEncodeUint64(value))
case bool:
buf.Write(LeEncodeBool(value))
case string:
buf.Write(LeEncodeString(value))
case []byte:
buf.Write(value)
case float32:
buf.Write(LeEncodeFloat32(value))
case float64:
buf.Write(LeEncodeFloat64(value))
default:
if err := binary.Write(buf, binary.LittleEndian, value); err != nil {
buf.Write(LeEncodeString(fmt.Sprintf("%v", value)))
}
}
}
return buf.Bytes()
}
func LeEncodeByLength(length int, values ...any) []byte {
b := LeEncode(values...)
if len(b) < length {
b = append(b, make([]byte, length-len(b))...)
} else if len(b) > length {
b = b[0:length]
}
return b
}
func LeDecode(b []byte, values ...any) error {
var (
err error
buf = bytes.NewBuffer(b)
)
for i := 0; i < len(values); i++ {
if err = binary.Read(buf, binary.LittleEndian, values[i]); err != nil {
return err
}
}
return nil
}
func LeEncodeString(s string) []byte {
return []byte(s)
}
func LeDecodeToString(b []byte) string {
return string(b)
}
func LeEncodeBool(b bool) []byte {
if b {
return []byte{1}
} else {
return []byte{0}
}
}
func LeEncodeInt(i int) []byte {
if i <= math.MaxInt8 {
return LeEncodeInt8(int8(i))
} else if i <= math.MaxInt16 {
return LeEncodeInt16(int16(i))
} else if i <= math.MaxInt32 {
return LeEncodeInt32(int32(i))
} else {
return LeEncodeInt64(int64(i))
}
}
func LeEncodeUint(i uint) []byte {
if i <= math.MaxUint8 {
return LeEncodeUint8(uint8(i))
} else if i <= math.MaxUint16 {
return LeEncodeUint16(uint16(i))
} else if i <= math.MaxUint32 {
return LeEncodeUint32(uint32(i))
} else {
return LeEncodeUint64(uint64(i))
}
}
func LeEncodeInt8(i int8) []byte {
return []byte{byte(i)}
}
func LeEncodeUint8(i uint8) []byte {
return []byte{i}
}
func LeEncodeInt16(i int16) []byte {
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, uint16(i))
return b
}
func LeEncodeUint16(i uint16) []byte {
b := make([]byte, 2)
binary.LittleEndian.PutUint16(b, i)
return b
}
func LeEncodeInt32(i int32) []byte {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, uint32(i))
return b
}
func LeEncodeUint32(i uint32) []byte {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, i)
return b
}
func LeEncodeInt64(i int64) []byte {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(i))
return b
}
func LeEncodeUint64(i uint64) []byte {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, i)
return b
}
func LeEncodeFloat32(f float32) []byte {
bits := math.Float32bits(f)
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, bits)
return b
}
func LeEncodeFloat64(f float64) []byte {
bits := math.Float64bits(f)
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, bits)
return b
}
func LeDecodeToInt(b []byte) int {
if len(b) < 2 {
return int(LeDecodeToUint8(b))
} else if len(b) < 3 {
return int(LeDecodeToUint16(b))
} else if len(b) < 5 {
return int(LeDecodeToUint32(b))
} else {
return int(LeDecodeToUint64(b))
}
}
func LeDecodeToUint(b []byte) uint {
if len(b) < 2 {
return uint(LeDecodeToUint8(b))
} else if len(b) < 3 {
return uint(LeDecodeToUint16(b))
} else if len(b) < 5 {
return uint(LeDecodeToUint32(b))
} else {
return uint(LeDecodeToUint64(b))
}
}
func LeDecodeToBool(b []byte) bool {
if len(b) == 0 {
return false
}
if bytes.Equal(b, make([]byte, len(b))) {
return false
}
return true
}
func LeDecodeToInt8(b []byte) int8 {
if len(b) == 0 {
panic(`empty slice given`)
}
return int8(b[0])
}
func LeDecodeToUint8(b []byte) uint8 {
if len(b) == 0 {
panic(`empty slice given`)
}
return b[0]
}
func LeDecodeToInt16(b []byte) int16 {
return int16(binary.LittleEndian.Uint16(LeFillUpSize(b, 2)))
}
func LeDecodeToUint16(b []byte) uint16 {
return binary.LittleEndian.Uint16(LeFillUpSize(b, 2))
}
func LeDecodeToInt32(b []byte) int32 {
return int32(binary.LittleEndian.Uint32(LeFillUpSize(b, 4)))
}
func LeDecodeToUint32(b []byte) uint32 {
return binary.LittleEndian.Uint32(LeFillUpSize(b, 4))
}
func LeDecodeToInt64(b []byte) int64 {
return int64(binary.LittleEndian.Uint64(LeFillUpSize(b, 8)))
}
func LeDecodeToUint64(b []byte) uint64 {
return binary.LittleEndian.Uint64(LeFillUpSize(b, 8))
}
func LeDecodeToFloat32(b []byte) float32 {
return math.Float32frombits(binary.LittleEndian.Uint32(LeFillUpSize(b, 4)))
}
func LeDecodeToFloat64(b []byte) float64 {
return math.Float64frombits(binary.LittleEndian.Uint64(LeFillUpSize(b, 8)))
}
// LeFillUpSize fills up the bytes `b` to given length `l` using LittleEndian.
//
// Note that it creates a new bytes slice by copying the original one to avoid changing
// the original parameter bytes.
func LeFillUpSize(b []byte, l int) []byte {
if len(b) >= l {
return b[:l]
}
c := make([]byte, l)
copy(c, b)
return c
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jericho-yu/util.git
git@gitee.com:jericho-yu/util.git
jericho-yu
util
util
v2.19.11

搜索帮助