summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-kv/v2/format
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-kv/v2/format')
-rw-r--r--vendor/codeberg.org/gruf/go-kv/v2/format/abi.go45
-rw-r--r--vendor/codeberg.org/gruf/go-kv/v2/format/format.go123
-rw-r--r--vendor/codeberg.org/gruf/go-kv/v2/format/methods.go8
3 files changed, 128 insertions, 48 deletions
diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go b/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go
index 815660a5e..b68d3cb73 100644
--- a/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go
+++ b/vendor/codeberg.org/gruf/go-kv/v2/format/abi.go
@@ -1,4 +1,4 @@
-//go:build go1.24 && !go1.25
+//go:build go1.24 && !go1.26
package format
@@ -39,26 +39,36 @@ type abi_EmptyInterface struct {
Data unsafe.Pointer
}
+// abi_NonEmptyInterface is a copy of the memory layout of abi.NonEmptyInterface{},
+// which is to say also the memory layout of any interface containing method(s).
+//
+// see: go/src/internal/abi/iface.go on 1.25+
+// see: go/src/reflect/value.go on 1.24
+type abi_NonEmptyInterface struct {
+ ITab uintptr
+ Data unsafe.Pointer
+}
+
// see: go/src/internal/abi/type.go Type.Kind()
func abi_Type_Kind(t reflect.Type) uint8 {
- iface := (*reflect_nonEmptyInterface)(unsafe.Pointer(&t))
- atype := (*abi_Type)(unsafe.Pointer(iface.word))
+ iface := (*abi_NonEmptyInterface)(unsafe.Pointer(&t))
+ atype := (*abi_Type)(unsafe.Pointer(iface.Data))
return atype.Kind_ & abi_KindMask
}
// see: go/src/internal/abi/type.go Type.IfaceIndir()
func abi_Type_IfaceIndir(t reflect.Type) bool {
- iface := (*reflect_nonEmptyInterface)(unsafe.Pointer(&t))
- atype := (*abi_Type)(unsafe.Pointer(iface.word))
+ iface := (*abi_NonEmptyInterface)(unsafe.Pointer(&t))
+ atype := (*abi_Type)(unsafe.Pointer(iface.Data))
return atype.Kind_&abi_KindDirectIface == 0
}
-// pack_iface packs a new reflect.nonEmptyInterface{} using shielded itab
-// pointer and data (word) pointer, returning a pointer for caller casting.
+// pack_iface packs a new reflect.nonEmptyInterface{} using shielded
+// itab and data pointer, returning a pointer for caller casting.
func pack_iface(itab uintptr, word unsafe.Pointer) unsafe.Pointer {
- return unsafe.Pointer(&reflect_nonEmptyInterface{
- itab: itab,
- word: word,
+ return unsafe.Pointer(&abi_NonEmptyInterface{
+ ITab: itab,
+ Data: word,
})
}
@@ -68,8 +78,8 @@ func pack_iface(itab uintptr, word unsafe.Pointer) unsafe.Pointer {
// this is useful for later calls to pack_iface for known type.
func get_iface_ITab[I any](t reflect.Type) uintptr {
s := reflect.New(t).Elem().Interface().(I)
- i := (*reflect_nonEmptyInterface)(unsafe.Pointer(&s))
- return i.itab
+ i := (*abi_NonEmptyInterface)(unsafe.Pointer(&s))
+ return i.ITab
}
// unpack_eface returns the .Data portion of an abi.EmptyInterface{}.
@@ -162,15 +172,6 @@ func reflect_map_elem_flags(elemType reflect.Type) reflect_flag {
return reflect_flag(abi_Type_Kind(elemType))
}
-// reflect_nonEmptyInterface is a copy of the memory layout of reflect.nonEmptyInterface,
-// which is also to say the memory layout of any non-empty (i.e. w/ method) interface.
-//
-// see: go/src/reflect/value.go
-type reflect_nonEmptyInterface struct {
- itab uintptr
- word unsafe.Pointer
-}
-
// reflect_Value is a copy of the memory layout of reflect.Value{}.
//
// see: go/src/reflect/value.go
@@ -190,7 +191,7 @@ func init() {
// as the reflect.nonEmptyInterface{}, which itself will be a pointer
// to the actual abi.Type{} that this reflect.Type{} is wrapping.
func reflect_type_data(t reflect.Type) unsafe.Pointer {
- return (*reflect_nonEmptyInterface)(unsafe.Pointer(&t)).word
+ return (*abi_NonEmptyInterface)(unsafe.Pointer(&t)).Data
}
// build_reflect_value manually builds a reflect.Value{} by setting the internal field members.
diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/format.go b/vendor/codeberg.org/gruf/go-kv/v2/format/format.go
index 2ab62eb06..69edcb597 100644
--- a/vendor/codeberg.org/gruf/go-kv/v2/format/format.go
+++ b/vendor/codeberg.org/gruf/go-kv/v2/format/format.go
@@ -8,6 +8,9 @@ import (
"unsafe"
)
+// Global formatter instance.
+var Global Formatter
+
// FormatFunc defines a function capable of formatting
// the value contained in State{}.P, based on args in
// State{}.A, storing the result in buffer State{}.B.
@@ -48,7 +51,7 @@ const ringsz = 16
// ptr_ring is a ring buffer of pointers,
// purposely stored as uintptrs as all we
-// need them for is value comparisons and
+// need them for is integer comparisons and
// we don't want to hold-up the GC.
type ptr_ring struct {
p [ringsz]uintptr
@@ -296,38 +299,60 @@ func (fmt *Formatter) get(t typenode) (fn FormatFunc) {
func (fmt *Formatter) getInterfaceType(t typenode) FormatFunc {
if t.rtype.NumMethod() == 0 {
return func(s *State) {
+ // Unpack empty interface.
eface := *(*any)(s.P)
s.P = unpack_eface(eface)
+
+ // Get reflected type information.
rtype := reflect.TypeOf(eface)
if rtype == nil {
appendNil(s)
return
}
+
+ // Check for ptr recursion.
if s.ifaces.contains(s.P) {
getPointerType(t)(s)
return
}
+
+ // Store value ptr.
s.ifaces.set(s.P)
+
+ // Wrap in our typenode for before load.
flags := reflect_iface_elem_flags(rtype)
t := new_typenode(rtype, flags)
+
+ // Load + pass to func.
fmt.loadOrStore(t)(s)
}
} else {
return func(s *State) {
+ // Unpack interface-with-method ptr.
iface := *(*interface{ M() })(s.P)
s.P = unpack_eface(iface)
+
+ // Get reflected type information.
rtype := reflect.TypeOf(iface)
if rtype == nil {
appendNil(s)
return
}
+
+ // Check for ptr recursion.
if s.ifaces.contains(s.P) {
getPointerType(t)(s)
return
}
+
+ // Store value ptr.
s.ifaces.set(s.P)
+
+ // Wrap in our typenode for before load.
flags := reflect_iface_elem_flags(rtype)
t := new_typenode(rtype, flags)
+
+ // Load + pass to func.
fmt.loadOrStore(t)(s)
}
}
@@ -360,14 +385,11 @@ func getIntType(t typenode) FormatFunc {
switch {
case s.A.AsNumber():
// fallthrough
- case s.A.AsQuotedText():
- s.B = strconv.AppendQuoteRune(s.B, *(*rune)(s.P))
- return
case s.A.AsQuotedASCII():
s.B = strconv.AppendQuoteRuneToASCII(s.B, *(*rune)(s.P))
return
- case s.A.AsText():
- s.B = AppendEscapeRune(s.B, *(*rune)(s.P))
+ case s.A.AsText() || s.A.AsQuotedText():
+ s.B = strconv.AppendQuoteRune(s.B, *(*rune)(s.P))
return
}
appendInt(s, int64(*(*int32)(s.P)))
@@ -388,12 +410,9 @@ func getUintType(t typenode) FormatFunc {
switch {
case s.A.AsNumber():
// fallthrough
- case s.A.AsQuotedText() || s.A.AsQuotedASCII():
+ case s.A.AsText() || s.A.AsQuotedText() || s.A.AsQuotedASCII():
s.B = AppendQuoteByte(s.B, *(*byte)(s.P))
return
- case s.A.AsText():
- s.B = AppendEscapeByte(s.B, *(*byte)(s.P))
- return
}
appendUint(s, uint64(*(*uint8)(s.P)))
})
@@ -468,10 +487,17 @@ func with_typestr_ptrs(t typenode, fn FormatFunc) FormatFunc {
if fn == nil {
panic("nil func")
}
+
+ // Check for type wrapping.
if !t.needs_typestr() {
return fn
}
+
+ // Get type string with pointers.
typestr := t.typestr_with_ptrs()
+
+ // Wrap format func to include
+ // type information when needed.
return func(s *State) {
if s.A.WithType() {
s.B = append(s.B, "("+typestr+")("...)
@@ -485,7 +511,22 @@ func with_typestr_ptrs(t typenode, fn FormatFunc) FormatFunc {
func appendString(s *State, v string) {
switch {
- case s.A.Logfmt() || s.A.WithType():
+ case s.A.WithType():
+ if len(v) > SingleTermLine || !IsSafeASCII(v) {
+ // Requires quoting AND escaping
+ s.B = strconv.AppendQuote(s.B, v)
+ } else if ContainsDoubleQuote(v) {
+ // Contains double quotes, needs escaping
+ s.B = append(s.B, '"')
+ s.B = AppendEscape(s.B, v)
+ s.B = append(s.B, '"')
+ } else {
+ // All else, needs quotes
+ s.B = append(s.B, '"')
+ s.B = append(s.B, v...)
+ s.B = append(s.B, '"')
+ }
+ case s.A.Logfmt():
if len(v) > SingleTermLine || !IsSafeASCII(v) {
// Requires quoting AND escaping
s.B = strconv.AppendQuote(s.B, v)
@@ -494,8 +535,7 @@ func appendString(s *State, v string) {
s.B = append(s.B, '"')
s.B = AppendEscape(s.B, v)
s.B = append(s.B, '"')
- } else if s.A.WithType() ||
- len(v) == 0 || ContainsSpaceOrTab(v) {
+ } else if len(v) == 0 || ContainsSpaceOrTab(v) {
// Contains space / empty, needs quotes
s.B = append(s.B, '"')
s.B = append(s.B, v...)
@@ -515,75 +555,114 @@ func appendString(s *State, v string) {
func appendInt(s *State, v int64) {
args := s.A.Int
+
+ // Set argument defaults.
if args == zeroArgs.Int {
args = defaultArgs.Int
}
+
+ // Add any padding.
if args.Pad > 0 {
const zeros = `00000000000000000000`
if args.Pad > len(zeros) {
panic("cannot pad > " + zeros)
}
+
if v == 0 {
s.B = append(s.B, zeros[:args.Pad]...)
return
}
+
+ // Get absolute.
abs := abs64(v)
+
+ // Get number of required chars.
chars := int(v / int64(args.Base))
if v%int64(args.Base) != 0 {
chars++
}
+
if abs != v {
+ // If this is a negative value,
+ // prepend minus ourselves and
+ // set value as the absolute.
s.B = append(s.B, '-')
v = abs
}
- if n := args.Pad - chars; n > 0 {
- s.B = append(s.B, zeros[:n]...)
- }
+
+ // Prepend required zeros.
+ n := args.Pad - chars
+ s.B = append(s.B, zeros[:n]...)
}
+
+ // Append value as signed integer w/ args.
s.B = strconv.AppendInt(s.B, v, args.Base)
}
func appendUint(s *State, v uint64) {
args := s.A.Int
+
+ // Set argument defaults.
if args == zeroArgs.Int {
args = defaultArgs.Int
}
+
+ // Add any padding.
if args.Pad > 0 {
const zeros = `00000000000000000000`
if args.Pad > len(zeros) {
panic("cannot pad > " + zeros)
}
+
if v == 0 {
s.B = append(s.B, zeros[:args.Pad]...)
return
}
+
+ // Get number of required chars.
chars := int(v / uint64(args.Base))
if v%uint64(args.Base) != 0 {
chars++
}
- if n := args.Pad - chars; n > 0 {
- s.B = append(s.B, zeros[:n]...)
- }
+
+ // Prepend required zeros.
+ n := args.Pad - chars
+ s.B = append(s.B, zeros[:n]...)
}
+
+ // Append value as unsigned integer w/ args.
s.B = strconv.AppendUint(s.B, v, args.Base)
}
func appendFloat(s *State, v float64, bits int) {
args := s.A.Float
+
+ // Set argument defaults.
if args == zeroArgs.Float {
args = defaultArgs.Float
}
- s.B = strconv.AppendFloat(s.B, float64(v), args.Fmt, args.Prec, bits)
+
+ // Append value as float${bit} w/ args.
+ s.B = strconv.AppendFloat(s.B, float64(v),
+ args.Fmt, args.Prec, bits)
}
func appendComplex(s *State, r, i float64, bits int) {
args := s.A.Complex
+
+ // Set argument defaults.
if args == zeroArgs.Complex {
args = defaultArgs.Complex
}
- s.B = strconv.AppendFloat(s.B, float64(r), args.Real.Fmt, args.Real.Prec, bits)
+
+ // Append real value as float${bit} w/ args.
+ s.B = strconv.AppendFloat(s.B, float64(r),
+ args.Real.Fmt, args.Real.Prec, bits)
s.B = append(s.B, '+')
- s.B = strconv.AppendFloat(s.B, float64(i), args.Imag.Fmt, args.Imag.Prec, bits)
+
+ // Append imag value as float${bit} w/ args.
+ s.B = strconv.AppendFloat(s.B, float64(i),
+ args.Imag.Fmt, args.Imag.Prec, bits)
s.B = append(s.B, 'i')
}
diff --git a/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go b/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go
index 7c1795771..fcbffd3a4 100644
--- a/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go
+++ b/vendor/codeberg.org/gruf/go-kv/v2/format/methods.go
@@ -45,7 +45,7 @@ func getInterfaceStringerType(t typenode) FormatFunc {
case true:
return with_typestr_ptrs(t, func(s *State) {
s.P = *(*unsafe.Pointer)(s.P)
- if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil {
+ if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil {
appendNil(s)
return
}
@@ -54,7 +54,7 @@ func getInterfaceStringerType(t typenode) FormatFunc {
})
case false:
return with_typestr_ptrs(t, func(s *State) {
- if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil {
+ if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil {
appendNil(s)
return
}
@@ -102,7 +102,7 @@ func getInterfaceErrorType(t typenode) FormatFunc {
case true:
return with_typestr_ptrs(t, func(s *State) {
s.P = *(*unsafe.Pointer)(s.P)
- if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil {
+ if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil {
appendNil(s)
return
}
@@ -111,7 +111,7 @@ func getInterfaceErrorType(t typenode) FormatFunc {
})
case false:
return with_typestr_ptrs(t, func(s *State) {
- if s.P == nil || (*reflect_nonEmptyInterface)(s.P).word == nil {
+ if s.P == nil || (*abi_NonEmptyInterface)(s.P).Data == nil {
appendNil(s)
return
}