mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-04 19:17:37 +08:00
onebot: pick Attr, Value from log/slog
[wip]
This commit is contained in:
parent
54995fc101
commit
55cb80dccc
78
pkg/onebot/attr.go
Normal file
78
pkg/onebot/attr.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package onebot
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Attr is a key-value pair.
|
||||||
|
type Attr struct {
|
||||||
|
Key string
|
||||||
|
Value Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns an Attr for a string value.
|
||||||
|
func String(key, value string) Attr {
|
||||||
|
return Attr{key, StringValue(value)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns an Attr for an int64.
|
||||||
|
func Int64(key string, value int64) Attr {
|
||||||
|
return Attr{key, Int64Value(value)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int converts an int to an int64 and returns
|
||||||
|
// an Attr with that value.
|
||||||
|
func Int(key string, value int) Attr {
|
||||||
|
return Int64(key, int64(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns an Attr for a uint64.
|
||||||
|
func Uint64(key string, v uint64) Attr {
|
||||||
|
return Attr{key, Uint64Value(v)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 returns an Attr for a floating-point number.
|
||||||
|
func Float64(key string, v float64) Attr {
|
||||||
|
return Attr{key, Float64Value(v)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool returns an Attr for a bool.
|
||||||
|
func Bool(key string, v bool) Attr {
|
||||||
|
return Attr{key, BoolValue(v)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns an Attr for a time.Time.
|
||||||
|
// It discards the monotonic portion.
|
||||||
|
func Time(key string, v time.Time) Attr {
|
||||||
|
return Attr{key, TimeValue(v)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration returns an Attr for a time.Duration.
|
||||||
|
func Duration(key string, v time.Duration) Attr {
|
||||||
|
return Attr{key, DurationValue(v)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group returns an Attr for a Group Value.
|
||||||
|
// The caller must not subsequently mutate the
|
||||||
|
// argument slice.
|
||||||
|
//
|
||||||
|
// Use Group to collect several Attrs under a single
|
||||||
|
// key on a log line, or as the result of LogValue
|
||||||
|
// in order to log a single value as multiple Attrs.
|
||||||
|
func Group(key string, as ...Attr) Attr {
|
||||||
|
return Attr{key, GroupValue(as...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any returns an Attr for the supplied value.
|
||||||
|
// See [Value.AnyValue] for how values are treated.
|
||||||
|
func Any(key string, value any) Attr {
|
||||||
|
return Attr{key, AnyValue(value)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Attr) String() string {
|
||||||
|
return a.Key + "=" + a.Value.String()
|
||||||
|
}
|
31
pkg/onebot/kind_string.go
Normal file
31
pkg/onebot/kind_string.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Code generated by "stringer -type=Kind -trimprefix=Kind"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package onebot
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[KindAny-0]
|
||||||
|
_ = x[KindBool-1]
|
||||||
|
_ = x[KindDuration-2]
|
||||||
|
_ = x[KindFloat64-3]
|
||||||
|
_ = x[KindInt64-4]
|
||||||
|
_ = x[KindString-5]
|
||||||
|
_ = x[KindTime-6]
|
||||||
|
_ = x[KindUint64-7]
|
||||||
|
_ = x[KindGroup-8]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _Kind_name = "AnyBoolDurationFloat64Int64StringTimeUint64Group"
|
||||||
|
|
||||||
|
var _Kind_index = [...]uint8{0, 3, 7, 15, 22, 27, 33, 37, 43, 48}
|
||||||
|
|
||||||
|
func (i Kind) String() string {
|
||||||
|
if i < 0 || i >= Kind(len(_Kind_index)-1) {
|
||||||
|
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
|
||||||
|
}
|
354
pkg/onebot/value.go
Normal file
354
pkg/onebot/value.go
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package onebot
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Value can represent any Go value, but unlike type any,
|
||||||
|
// it can represent most small values without an allocation.
|
||||||
|
// The zero Value corresponds to nil.
|
||||||
|
type Value struct {
|
||||||
|
_ [0]func() // disallow ==
|
||||||
|
num uint64 // hold number value
|
||||||
|
any any // hold Kind or other value
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
stringptr *byte // used in Value.any when the Value is a string
|
||||||
|
groupptr *Attr // used in Value.any when the Value is a []Attr
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate stringer -type=Kind -trimprefix=Kind
|
||||||
|
|
||||||
|
// Kind is the kind of Value.
|
||||||
|
type Kind int
|
||||||
|
|
||||||
|
const (
|
||||||
|
KindAny Kind = iota
|
||||||
|
KindBool
|
||||||
|
KindDuration
|
||||||
|
KindFloat64
|
||||||
|
KindInt64
|
||||||
|
KindString
|
||||||
|
KindTime
|
||||||
|
KindUint64
|
||||||
|
KindGroup
|
||||||
|
)
|
||||||
|
|
||||||
|
// Unexported version of Kind, just so we can store Kinds in Values.
|
||||||
|
// (No user-provided value has this type.)
|
||||||
|
type kind Kind
|
||||||
|
|
||||||
|
// Kind returns v's Kind.
|
||||||
|
func (v Value) Kind() Kind {
|
||||||
|
switch x := v.any.(type) {
|
||||||
|
case Kind:
|
||||||
|
return x
|
||||||
|
case stringptr:
|
||||||
|
return KindString
|
||||||
|
case timeLocation:
|
||||||
|
return KindTime
|
||||||
|
case groupptr:
|
||||||
|
return KindGroup
|
||||||
|
case kind: // a kind is just a wrapper for a Kind
|
||||||
|
return KindAny
|
||||||
|
default:
|
||||||
|
return KindAny
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////// Constructors
|
||||||
|
|
||||||
|
// StringValue returns a new Value for a string.
|
||||||
|
func StringValue(value string) Value {
|
||||||
|
return Value{num: uint64(len(value)), any: stringptr(unsafe.StringData(value))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IntValue returns a Value for an int.
|
||||||
|
func IntValue(v int) Value {
|
||||||
|
return Int64Value(int64(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64Value returns a Value for an int64.
|
||||||
|
func Int64Value(v int64) Value {
|
||||||
|
return Value{num: uint64(v), any: KindInt64}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64Value returns a Value for a uint64.
|
||||||
|
func Uint64Value(v uint64) Value {
|
||||||
|
return Value{num: v, any: KindUint64}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64Value returns a Value for a floating-point number.
|
||||||
|
func Float64Value(v float64) Value {
|
||||||
|
return Value{num: math.Float64bits(v), any: KindFloat64}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolValue returns a Value for a bool.
|
||||||
|
func BoolValue(v bool) Value {
|
||||||
|
u := uint64(0)
|
||||||
|
if v {
|
||||||
|
u = 1
|
||||||
|
}
|
||||||
|
return Value{num: u, any: KindBool}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unexported version of *time.Location, just so we can store *time.Locations in
|
||||||
|
// Values. (No user-provided value has this type.)
|
||||||
|
type timeLocation *time.Location
|
||||||
|
|
||||||
|
// TimeValue returns a Value for a time.Time.
|
||||||
|
// It discards the monotonic portion.
|
||||||
|
func TimeValue(v time.Time) Value {
|
||||||
|
if v.IsZero() {
|
||||||
|
// UnixNano on the zero time is undefined, so represent the zero time
|
||||||
|
// with a nil *time.Location instead. time.Time.Location method never
|
||||||
|
// returns nil, so a Value with any == timeLocation(nil) cannot be
|
||||||
|
// mistaken for any other Value, time.Time or otherwise.
|
||||||
|
return Value{any: timeLocation(nil)}
|
||||||
|
}
|
||||||
|
return Value{num: uint64(v.UnixNano()), any: timeLocation(v.Location())}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DurationValue returns a Value for a time.Duration.
|
||||||
|
func DurationValue(v time.Duration) Value {
|
||||||
|
return Value{num: uint64(v.Nanoseconds()), any: KindDuration}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupValue returns a new Value for a list of Attrs.
|
||||||
|
// The caller must not subsequently mutate the argument slice.
|
||||||
|
func GroupValue(as ...Attr) Value {
|
||||||
|
return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyValue returns a Value for the supplied value.
|
||||||
|
//
|
||||||
|
// If the supplied value is of type Value, it is returned
|
||||||
|
// unmodified.
|
||||||
|
//
|
||||||
|
// Given a value of one of Go's predeclared string, bool, or
|
||||||
|
// (non-complex) numeric types, AnyValue returns a Value of kind
|
||||||
|
// String, Bool, Uint64, Int64, or Float64. The width of the
|
||||||
|
// original numeric type is not preserved.
|
||||||
|
//
|
||||||
|
// Given a time.Time or time.Duration value, AnyValue returns a Value of kind
|
||||||
|
// KindTime or KindDuration. The monotonic time is not preserved.
|
||||||
|
//
|
||||||
|
// For nil, or values of all other types, including named types whose
|
||||||
|
// underlying type is numeric, AnyValue returns a value of kind KindAny.
|
||||||
|
func AnyValue(v any) Value {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
return StringValue(v)
|
||||||
|
case int:
|
||||||
|
return Int64Value(int64(v))
|
||||||
|
case uint:
|
||||||
|
return Uint64Value(uint64(v))
|
||||||
|
case int64:
|
||||||
|
return Int64Value(v)
|
||||||
|
case uint64:
|
||||||
|
return Uint64Value(v)
|
||||||
|
case bool:
|
||||||
|
return BoolValue(v)
|
||||||
|
case time.Duration:
|
||||||
|
return DurationValue(v)
|
||||||
|
case time.Time:
|
||||||
|
return TimeValue(v)
|
||||||
|
case uint8:
|
||||||
|
return Uint64Value(uint64(v))
|
||||||
|
case uint16:
|
||||||
|
return Uint64Value(uint64(v))
|
||||||
|
case uint32:
|
||||||
|
return Uint64Value(uint64(v))
|
||||||
|
case uintptr:
|
||||||
|
return Uint64Value(uint64(v))
|
||||||
|
case int8:
|
||||||
|
return Int64Value(int64(v))
|
||||||
|
case int16:
|
||||||
|
return Int64Value(int64(v))
|
||||||
|
case int32:
|
||||||
|
return Int64Value(int64(v))
|
||||||
|
case float64:
|
||||||
|
return Float64Value(v)
|
||||||
|
case float32:
|
||||||
|
return Float64Value(float64(v))
|
||||||
|
case []Attr:
|
||||||
|
return GroupValue(v...)
|
||||||
|
case Kind:
|
||||||
|
return Value{any: kind(v)}
|
||||||
|
case Value:
|
||||||
|
return v
|
||||||
|
default:
|
||||||
|
return Value{any: v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////// Accessors
|
||||||
|
|
||||||
|
// Any returns v's value as an any.
|
||||||
|
func (v Value) Any() any {
|
||||||
|
switch v.Kind() {
|
||||||
|
case KindAny:
|
||||||
|
if k, ok := v.any.(kind); ok {
|
||||||
|
return Kind(k)
|
||||||
|
}
|
||||||
|
return v.any
|
||||||
|
case KindGroup:
|
||||||
|
return v.group()
|
||||||
|
case KindInt64:
|
||||||
|
return int64(v.num)
|
||||||
|
case KindUint64:
|
||||||
|
return v.num
|
||||||
|
case KindFloat64:
|
||||||
|
return v.float()
|
||||||
|
case KindString:
|
||||||
|
return v.str()
|
||||||
|
case KindBool:
|
||||||
|
return v.bool()
|
||||||
|
case KindDuration:
|
||||||
|
return v.duration()
|
||||||
|
case KindTime:
|
||||||
|
return v.time()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("bad kind: %s", v.Kind()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns Value's value as a string, formatted like fmt.Sprint. Unlike
|
||||||
|
// the methods Int64, Float64, and so on, which panic if v is of the
|
||||||
|
// wrong kind, String never panics.
|
||||||
|
func (v Value) String() string {
|
||||||
|
if sp, ok := v.any.(stringptr); ok {
|
||||||
|
return unsafe.String(sp, v.num)
|
||||||
|
}
|
||||||
|
var buf []byte
|
||||||
|
return string(v.append(buf))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Value) str() string {
|
||||||
|
return unsafe.String(v.any.(stringptr), v.num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns v's value as an int64. It panics
|
||||||
|
// if v is not a signed integer.
|
||||||
|
func (v Value) Int64() int64 {
|
||||||
|
if g, w := v.Kind(), KindInt64; g != w {
|
||||||
|
panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
|
||||||
|
}
|
||||||
|
return int64(v.num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uint64 returns v's value as a uint64. It panics
|
||||||
|
// if v is not an unsigned integer.
|
||||||
|
func (v Value) Uint64() uint64 {
|
||||||
|
if g, w := v.Kind(), KindUint64; g != w {
|
||||||
|
panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
|
||||||
|
}
|
||||||
|
return v.num
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bool returns v's value as a bool. It panics
|
||||||
|
// if v is not a bool.
|
||||||
|
func (v Value) Bool() bool {
|
||||||
|
if g, w := v.Kind(), KindBool; g != w {
|
||||||
|
panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
|
||||||
|
}
|
||||||
|
return v.bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Value) bool() bool {
|
||||||
|
return v.num == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duration returns v's value as a time.Duration. It panics
|
||||||
|
// if v is not a time.Duration.
|
||||||
|
func (v Value) Duration() time.Duration {
|
||||||
|
if g, w := v.Kind(), KindDuration; g != w {
|
||||||
|
panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.duration()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Value) duration() time.Duration {
|
||||||
|
return time.Duration(int64(v.num))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64 returns v's value as a float64. It panics
|
||||||
|
// if v is not a float64.
|
||||||
|
func (v Value) Float64() float64 {
|
||||||
|
if g, w := v.Kind(), KindFloat64; g != w {
|
||||||
|
panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.float()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Value) float() float64 {
|
||||||
|
return math.Float64frombits(v.num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns v's value as a time.Time. It panics
|
||||||
|
// if v is not a time.Time.
|
||||||
|
func (v Value) Time() time.Time {
|
||||||
|
if g, w := v.Kind(), KindTime; g != w {
|
||||||
|
panic(fmt.Sprintf("Value kind is %s, not %s", g, w))
|
||||||
|
}
|
||||||
|
return v.time()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Value) time() time.Time {
|
||||||
|
loc := v.any.(timeLocation)
|
||||||
|
if loc == nil {
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
return time.Unix(0, int64(v.num)).In(loc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group returns v's value as a []Attr.
|
||||||
|
// It panics if v's Kind is not KindGroup.
|
||||||
|
func (v Value) Group() []Attr {
|
||||||
|
if sp, ok := v.any.(groupptr); ok {
|
||||||
|
return unsafe.Slice(sp, v.num)
|
||||||
|
}
|
||||||
|
panic("Group: bad kind")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v Value) group() []Attr {
|
||||||
|
return unsafe.Slice((*Attr)(v.any.(groupptr)), v.num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// append appends a text representation of v to dst.
|
||||||
|
// v is formatted as with fmt.Sprint.
|
||||||
|
func (v Value) append(dst []byte) []byte {
|
||||||
|
switch v.Kind() {
|
||||||
|
case KindString:
|
||||||
|
return append(dst, v.str()...)
|
||||||
|
case KindInt64:
|
||||||
|
return strconv.AppendInt(dst, int64(v.num), 10)
|
||||||
|
case KindUint64:
|
||||||
|
return strconv.AppendUint(dst, v.num, 10)
|
||||||
|
case KindFloat64:
|
||||||
|
return strconv.AppendFloat(dst, v.float(), 'g', -1, 64)
|
||||||
|
case KindBool:
|
||||||
|
return strconv.AppendBool(dst, v.bool())
|
||||||
|
case KindDuration:
|
||||||
|
return append(dst, v.duration().String()...)
|
||||||
|
case KindTime:
|
||||||
|
return append(dst, v.time().String()...)
|
||||||
|
case KindGroup:
|
||||||
|
return fmt.Append(dst, v.group())
|
||||||
|
case KindAny:
|
||||||
|
return fmt.Append(dst, v.any)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("bad kind: %s", v.Kind()))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user