diff options
author | 2022-07-19 09:47:55 +0100 | |
---|---|---|
committer | 2022-07-19 10:47:55 +0200 | |
commit | 098dbe6ff4f59652181c8e0e3873fbfcf0e65ea3 (patch) | |
tree | 17036ad9db68c3080e1e91279c8bce9f9ea6e5c3 /vendor/codeberg.org | |
parent | [bugfix] Markdown format fixes (#718) (diff) | |
download | gotosocial-098dbe6ff4f59652181c8e0e3873fbfcf0e65ea3.tar.xz |
[chore] use our own logging implementation (#716)
* first commit
Signed-off-by: kim <grufwub@gmail.com>
* replace logging with our own log library
Signed-off-by: kim <grufwub@gmail.com>
* fix imports
Signed-off-by: kim <grufwub@gmail.com>
* fix log imports
Signed-off-by: kim <grufwub@gmail.com>
* add license text
Signed-off-by: kim <grufwub@gmail.com>
* fix package import cycle between config and log package
Signed-off-by: kim <grufwub@gmail.com>
* fix empty kv.Fields{} being passed to WithFields()
Signed-off-by: kim <grufwub@gmail.com>
* fix uses of log.WithFields() with whitespace issues and empty slices
Signed-off-by: kim <grufwub@gmail.com>
* *linter related grumbling*
Signed-off-by: kim <grufwub@gmail.com>
* gofmt the codebase! also fix more log.WithFields() formatting issues
Signed-off-by: kim <grufwub@gmail.com>
* update testrig code to match new changes
Signed-off-by: kim <grufwub@gmail.com>
* fix error wrapping in non fmt.Errorf function
Signed-off-by: kim <grufwub@gmail.com>
* add benchmarking of log.Caller() vs non-cached
Signed-off-by: kim <grufwub@gmail.com>
* fix syslog tests, add standard build tags to test runner to ensure consistency
Signed-off-by: kim <grufwub@gmail.com>
* make syslog tests more robust
Signed-off-by: kim <grufwub@gmail.com>
* fix caller depth arithmatic (is that how you spell it?)
Signed-off-by: kim <grufwub@gmail.com>
* update to use unkeyed fields in kv.Field{} instances
Signed-off-by: kim <grufwub@gmail.com>
* update go-kv library
Signed-off-by: kim <grufwub@gmail.com>
* update libraries list
Signed-off-by: kim <grufwub@gmail.com>
* fuck you linter get nerfed
Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
Diffstat (limited to 'vendor/codeberg.org')
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/LICENSE | 9 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/README.md | 9 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/benchmark.png | bin | 0 -> 97592 bytes | |||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/field.go | 105 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/field_fmt.go | 36 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/field_format.go | 35 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/README.md | 5 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/benchmark.png | bin | 0 -> 36505 bytes | |||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/format.go | 922 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/formatter.go | 349 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/format/util.go | 56 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-kv/util.go | 71 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-logger/v2/LICENSE | 9 | ||||
-rw-r--r-- | vendor/codeberg.org/gruf/go-logger/v2/level/levels.go | 49 |
14 files changed, 1655 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-kv/LICENSE b/vendor/codeberg.org/gruf/go-kv/LICENSE new file mode 100644 index 000000000..b7c4417ac --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2021 gruf + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/codeberg.org/gruf/go-kv/README.md b/vendor/codeberg.org/gruf/go-kv/README.md new file mode 100644 index 000000000..fa4735868 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/README.md @@ -0,0 +1,9 @@ +# go-kv + +This library provides a key-value field structure `kv.Field{}` that plays well with the `"fmt"` package. It gives an easy means of appending key-value fields to log entries, in a manner that also happens to look nice! (it's not far removed from using a `map[string]interface{}`). + +The formatting for these key-value fields is handled by the `"fmt"` package by default. If you set the `kvformat` build tag then it will use a custom formatting library found under `format/`. You can see the benchmarks for both below. + + + +TODO: benchmarks comparing these to using `fmt.Sprintf("%q=%+v", ...)` yourself.
\ No newline at end of file diff --git a/vendor/codeberg.org/gruf/go-kv/benchmark.png b/vendor/codeberg.org/gruf/go-kv/benchmark.png Binary files differnew file mode 100644 index 000000000..08d838643 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/benchmark.png diff --git a/vendor/codeberg.org/gruf/go-kv/field.go b/vendor/codeberg.org/gruf/go-kv/field.go new file mode 100644 index 000000000..7ff6f1ca3 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/field.go @@ -0,0 +1,105 @@ +package kv + +import ( + "codeberg.org/gruf/go-byteutil" +) + +// bufsize is the default buffer size per field to alloc +// when calling .AppendFormat() from within .String(). +const bufsize = 64 + +// Fields is a typedef for a []Field slice to provide +// slightly more performant string formatting for multiples. +type Fields []Field + +// Get will return the field with given 'key'. +func (f Fields) Get(key string) (*Field, bool) { + for i := 0; i < len(f); i++ { + if f[i].K == key { + return &f[i], true + } + } + return nil, false +} + +// Set will set an existing field with 'key' to 'value', or append new. +func (f *Fields) Set(key string, value interface{}) { + for i := 0; i < len(*f); i++ { + // Update existing value + if (*f)[i].K == key { + (*f)[i].V = value + return + } + } + + // Append new field + *f = append(*f, Field{ + K: key, + V: value, + }) +} + +// AppendFormat appends a string representation of receiving Field(s) to 'b'. +func (f Fields) AppendFormat(buf *byteutil.Buffer, vbose bool) { + for i := 0; i < len(f); i++ { + f[i].AppendFormat(buf, vbose) + buf.WriteByte(' ') + } + if len(f) > 0 { + buf.Truncate(1) + } +} + +// String returns a string representation of receiving Field(s). +func (f Fields) String() string { + b := make([]byte, 0, bufsize*len(f)) + buf := byteutil.Buffer{B: b} + f.AppendFormat(&buf, false) + return buf.String() +} + +// GoString performs .String() but with type prefix. +func (f Fields) GoString() string { + b := make([]byte, 0, bufsize*len(f)) + buf := byteutil.Buffer{B: b} + f.AppendFormat(&buf, true) + return "kv.Fields{" + buf.String() + "}" +} + +// Field represents an individual key-value field. +type Field struct { + K string // Field key + V interface{} // Field value +} + +// Key returns the formatted key string of this Field. +func (f Field) Key() string { + buf := byteutil.Buffer{B: make([]byte, 0, bufsize/2)} + appendQuoteKey(&buf, f.K) + return buf.String() +} + +// String will return a string representation of this Field +// of the form `key=value` where `value` is formatted using +// fmt package's `%+v` directive. If the .X = true (verbose), +// then it uses '%#v'. Both key and value are escaped and +// quoted if necessary to fit on single line. +// +// If the `kvformat` build tag is provided, the formatting +// will be performed by the `kv/format` package. In this case +// the value will be formatted using the `{:v}` directive, or +// `{:?}` if .X = true (verbose). +func (f Field) String() string { + b := make([]byte, 0, bufsize) + buf := byteutil.Buffer{B: b} + f.AppendFormat(&buf, false) + return buf.String() +} + +// GoString performs .String() but with verbose always enabled. +func (f Field) GoString() string { + b := make([]byte, 0, bufsize) + buf := byteutil.Buffer{B: b} + f.AppendFormat(&buf, true) + return buf.String() +} diff --git a/vendor/codeberg.org/gruf/go-kv/field_fmt.go b/vendor/codeberg.org/gruf/go-kv/field_fmt.go new file mode 100644 index 000000000..c62393fe0 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/field_fmt.go @@ -0,0 +1,36 @@ +//go:build !kvformat +// +build !kvformat + +package kv + +import ( + "fmt" + + "codeberg.org/gruf/go-byteutil" +) + +// AppendFormat will append formatted format of Field to 'buf'. See .String() for details. +func (f Field) AppendFormat(buf *byteutil.Buffer, vbose bool) { + var fmtstr string + if vbose /* verbose */ { + fmtstr = `%#v` + } else /* regular */ { + fmtstr = `%+v` + } + appendQuoteKey(buf, f.K) + buf.WriteByte('=') + appendQuoteValue(buf, fmt.Sprintf(fmtstr, f.V)) +} + +// Value returns the formatted value string of this Field. +func (f Field) Value(vbose bool) string { + var fmtstr string + if vbose /* verbose */ { + fmtstr = `%#v` + } else /* regular */ { + fmtstr = `%+v` + } + buf := byteutil.Buffer{B: make([]byte, 0, bufsize/2)} + appendQuoteValue(&buf, fmt.Sprintf(fmtstr, f.V)) + return buf.String() +} diff --git a/vendor/codeberg.org/gruf/go-kv/field_format.go b/vendor/codeberg.org/gruf/go-kv/field_format.go new file mode 100644 index 000000000..db1ffc721 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/field_format.go @@ -0,0 +1,35 @@ +//go:build kvformat +// +build kvformat + +package kv + +import ( + "codeberg.org/gruf/go-byteutil" + "codeberg.org/gruf/go-kv/format" +) + +// AppendFormat will append formatted format of Field to 'buf'. See .String() for details. +func (f Field) AppendFormat(buf *byteutil.Buffer, vbose bool) { + var fmtstr string + if vbose /* verbose */ { + fmtstr = "{:?}" + } else /* regular */ { + fmtstr = "{:v}" + } + appendQuoteKey(buf, f.K) + buf.WriteByte('=') + format.Appendf(buf, fmtstr, f.V) +} + +// Value returns the formatted value string of this Field. +func (f Field) Value(vbose bool) string { + var fmtstr string + if vbose /* verbose */ { + fmtstr = "{:?}" + } else /* regular */ { + fmtstr = "{:v}" + } + buf := byteutil.Buffer{B: make([]byte, 0, bufsize/2)} + format.Appendf(&buf, fmtstr, f.V) + return buf.String() +} diff --git a/vendor/codeberg.org/gruf/go-kv/format/README.md b/vendor/codeberg.org/gruf/go-kv/format/README.md new file mode 100644 index 000000000..fe7b2338d --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/format/README.md @@ -0,0 +1,5 @@ +String formatting package using Rust-style formatting directives, geared specifcally towards formatting arguments for key-value log output. Provides ONLY default, key, value and verbose formatting directives. For most formatting cases you will be best served by `"fmt"`. + +Generally more visually friendly than `"fmt"` and performance is much improved. + +
\ No newline at end of file diff --git a/vendor/codeberg.org/gruf/go-kv/format/benchmark.png b/vendor/codeberg.org/gruf/go-kv/format/benchmark.png Binary files differnew file mode 100644 index 000000000..7151fbc55 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/format/benchmark.png diff --git a/vendor/codeberg.org/gruf/go-kv/format/format.go b/vendor/codeberg.org/gruf/go-kv/format/format.go new file mode 100644 index 000000000..df5a94b7c --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/format/format.go @@ -0,0 +1,922 @@ +package format + +import ( + "reflect" + "strconv" + "unicode/utf8" + + "codeberg.org/gruf/go-byteutil" +) + +const ( + // Flag bit constants, note they are prioritised in this order. + IsKeyBit = uint8(1) << 0 // set to indicate key formatting + VboseBit = uint8(1) << 1 // set to indicate verbose formatting + IsValBit = uint8(1) << 2 // set to indicate value formatting + PanicBit = uint8(1) << 3 // set after panic to prevent recursion +) + +// format provides formatting of values into a Buffer. +type format struct { + // Flags are the currently set value flags. + Flags uint8 + + // Derefs is the current value dereference count. + Derefs uint8 + + // CurDepth is the current Format iterator depth. + CurDepth uint8 + + // VType is the current value type. + VType string + + // Config is the set Formatter config (MUST NOT be nil). + Config *Formatter + + // Buffer is the currently set output buffer. + Buffer *byteutil.Buffer +} + +// AtMaxDepth returns whether format is currently at max depth. +func (f format) AtMaxDepth() bool { + return f.CurDepth > f.Config.MaxDepth +} + +// Key returns whether the isKey flag is set. +func (f format) Key() bool { + return (f.Flags & IsKeyBit) != 0 +} + +// Value returns whether the isVal flag is set. +func (f format) Value() bool { + return (f.Flags & IsValBit) != 0 +} + +// Verbose returns whether the verbose flag is set. +func (f format) Verbose() bool { + return (f.Flags & VboseBit) != 0 +} + +// Panic returns whether the panic flag is set. +func (f format) Panic() bool { + return (f.Flags & PanicBit) != 0 +} + +// SetKey returns format instance with the IsKey bit set to true, +// note this resets the dereference count. +func (f format) SetKey() format { + flags := f.Flags | IsKeyBit + flags &= ^IsValBit + return format{ + Flags: flags, + CurDepth: f.CurDepth, + Config: f.Config, + Buffer: f.Buffer, + } +} + +// SetValue returns format instance with the IsVal bit set to true, +// note this resets the dereference count. +func (f format) SetValue() format { + flags := f.Flags | IsValBit + flags &= ^IsKeyBit + return format{ + Flags: flags, + CurDepth: f.CurDepth, + Config: f.Config, + Buffer: f.Buffer, + } +} + +// SetVerbose returns format instance with the Vbose bit set to true, +// note this resets the dereference count. +func (f format) SetVerbose() format { + return format{ + Flags: f.Flags | VboseBit, + CurDepth: f.CurDepth, + Config: f.Config, + Buffer: f.Buffer, + } +} + +// SetPanic returns format instance with the panic bit set to true, +// note this resets the dereference count and sets IsVal (unsetting IsKey) bit. +func (f format) SetPanic() format { + flags := f.Flags | PanicBit + flags |= IsValBit + flags &= ^IsKeyBit + return format{ + Flags: flags, + CurDepth: f.CurDepth, + Config: f.Config, + Buffer: f.Buffer, + } +} + +// IncrDepth returns format instance with depth incremented and derefs reset. +func (f format) IncrDepth() format { + return format{ + Flags: f.Flags, + Derefs: f.Derefs, + CurDepth: f.CurDepth + 1, + Config: f.Config, + Buffer: f.Buffer, + } +} + +// IncrDerefs returns format instance with dereference count incremented. +func (f format) IncrDerefs() format { + return format{ + Flags: f.Flags, + Derefs: f.Derefs + 1, + CurDepth: f.CurDepth, + Config: f.Config, + Buffer: f.Buffer, + } +} + +func (f format) AppendType() { + const derefs = `********************************` + + `********************************` + + `********************************` + + `********************************` + + `********************************` + + `********************************` + + `********************************` + + `********************************` + f.Buffer.B = append(f.Buffer.B, derefs[:f.Derefs]...) + f.Buffer.B = append(f.Buffer.B, f.VType...) +} + +func (f format) AppendNil() { + if !f.Verbose() { + f.Buffer.B = append(f.Buffer.B, `nil`...) + return + } + + // Append nil with type + f.Buffer.B = append(f.Buffer.B, '(') + f.AppendType() + f.Buffer.B = append(f.Buffer.B, `)(nil`...) + f.Buffer.B = append(f.Buffer.B, ')') +} + +func (f format) AppendByte(b byte) { + switch { + // Always quoted + case f.Key(): + f.Buffer.B = append(f.Buffer.B, '\'') + f.Buffer.B = append(f.Buffer.B, byte2str(b)...) + f.Buffer.B = append(f.Buffer.B, '\'') + + // Always quoted ASCII with type + case f.Verbose(): + f._AppendPrimitiveTyped(func(f format) { + f.Buffer.B = append(f.Buffer.B, '\'') + f.Buffer.B = append(f.Buffer.B, byte2str(b)...) + f.Buffer.B = append(f.Buffer.B, '\'') + }) + + // Always quoted + case f.Value(): + f.Buffer.B = append(f.Buffer.B, '\'') + f.Buffer.B = append(f.Buffer.B, byte2str(b)...) + f.Buffer.B = append(f.Buffer.B, '\'') + + // Append as raw byte + default: + f.Buffer.B = append(f.Buffer.B, b) + } +} + +func (f format) AppendBytes(b []byte) { + switch { + // Bytes CAN be nil formatted + case b == nil: + f.AppendNil() + + // Handle bytes as string key + case f.Key(): + f.AppendStringKey(b2s(b)) + + // Append as separate ASCII quoted bytes in slice + case f.Verbose(): + f._AppendArrayTyped(func(f format) { + for i := 0; i < len(b); i++ { + f.Buffer.B = append(f.Buffer.B, '\'') + f.Buffer.B = append(f.Buffer.B, byte2str(b[i])...) + f.Buffer.B = append(f.Buffer.B, `',`...) + } + if len(b) > 0 { + f.Buffer.Truncate(1) + } + }) + + // Append as quoted string + case f.Value(): + f.AppendStringQuoted(b2s(b)) + + // Append as raw bytes + default: + f.Buffer.B = append(f.Buffer.B, b...) + } +} + +func (f format) AppendRune(r rune) { + switch { + // Quoted only if spaces/requires escaping + case f.Key(): + f.AppendRuneKey(r) + + // Always quoted ASCII with type + case f.Verbose(): + f._AppendPrimitiveTyped(func(f format) { + f.Buffer.B = strconv.AppendQuoteRuneToASCII(f.Buffer.B, r) + }) + + // Always quoted value + case f.Value(): + f.Buffer.B = strconv.AppendQuoteRune(f.Buffer.B, r) + + // Append as raw rune + default: + f.Buffer.WriteRune(r) + } +} + +func (f format) AppendRuneKey(r rune) { + if utf8.RuneLen(r) > 1 && (r < ' ' && r != '\t') || r == '`' || r == '\u007F' { + // Quote and escape this rune + f.Buffer.B = strconv.AppendQuoteRuneToASCII(f.Buffer.B, r) + } else { + // Simply append rune + f.Buffer.WriteRune(r) + } +} + +func (f format) AppendRunes(r []rune) { + switch { + // Runes CAN be nil formatted + case r == nil: + f.AppendNil() + + // Handle bytes as string key + case f.Key(): + f.AppendStringKey(string(r)) + + // Append as separate ASCII quoted bytes in slice + case f.Verbose(): + f._AppendArrayTyped(func(f format) { + for i := 0; i < len(r); i++ { + f.Buffer.B = strconv.AppendQuoteRuneToASCII(f.Buffer.B, r[i]) + f.Buffer.B = append(f.Buffer.B, ',') + } + if len(r) > 0 { + f.Buffer.Truncate(1) + } + }) + + // Append as quoted string + case f.Value(): + f.AppendStringQuoted(string(r)) + + // Append as raw bytes + default: + for i := 0; i < len(r); i++ { + f.Buffer.WriteRune(r[i]) + } + } +} + +func (f format) AppendString(s string) { + switch { + // Quoted only if spaces/requires escaping + case f.Key(): + f.AppendStringKey(s) + + // Always quoted with type + case f.Verbose(): + f._AppendPrimitiveTyped(func(f format) { + f.AppendStringQuoted(s) + }) + + // Always quoted string + case f.Value(): + f.AppendStringQuoted(s) + + // All else + default: + f.Buffer.B = append(f.Buffer.B, s...) + } +} + +func (f format) AppendStringKey(s string) { + if !strconv.CanBackquote(s) { + // Requires quoting AND escaping + f.Buffer.B = strconv.AppendQuote(f.Buffer.B, s) + } else if ContainsDoubleQuote(s) { + // Contains double quotes, needs escaping + f.Buffer.B = AppendEscape(f.Buffer.B, s) + } else if len(s) < 1 || ContainsSpaceOrTab(s) { + // Contains space, needs quotes + f.Buffer.B = append(f.Buffer.B, '"') + f.Buffer.B = append(f.Buffer.B, s...) + f.Buffer.B = append(f.Buffer.B, '"') + } else { + // All else write as-is + f.Buffer.B = append(f.Buffer.B, s...) + } +} + +func (f format) AppendStringQuoted(s string) { + if !strconv.CanBackquote(s) { + // Requires quoting AND escaping + f.Buffer.B = strconv.AppendQuote(f.Buffer.B, s) + } else if ContainsDoubleQuote(s) { + // Contains double quotes, needs escaping + f.Buffer.B = append(f.Buffer.B, '"') + f.Buffer.B = AppendEscape(f.Buffer.B, s) + f.Buffer.B = append(f.Buffer.B, '"') + } else { + // Simply append with quotes + f.Buffer.B = append(f.Buffer.B, '"') + f.Buffer.B = append(f.Buffer.B, s...) + f.Buffer.B = append(f.Buffer.B, '"') + } +} + +func (f format) AppendBool(b bool) { + if f.Verbose() { + // Append as bool with type information + f._AppendPrimitiveTyped(func(f format) { + f.Buffer.B = strconv.AppendBool(f.Buffer.B, b) + }) + } else { + // Simply append as bool + f.Buffer.B = strconv.AppendBool(f.Buffer.B, b) + } +} + +func (f format) AppendInt(i int64) { + f._AppendPrimitiveType(func(f format) { + f.Buffer.B = strconv.AppendInt(f.Buffer.B, i, 10) + }) +} + +func (f format) AppendUint(u uint64) { + f._AppendPrimitiveType(func(f format) { + f.Buffer.B = strconv.AppendUint(f.Buffer.B, u, 10) + }) +} + +func (f format) AppendFloat(l float64) { + f._AppendPrimitiveType(func(f format) { + f.AppendFloatValue(l) + }) +} + +func (f format) AppendFloatValue(l float64) { + f.Buffer.B = strconv.AppendFloat(f.Buffer.B, l, 'f', -1, 64) +} + +func (f format) AppendComplex(c complex128) { + f._AppendPrimitiveType(func(f format) { + f.AppendFloatValue(real(c)) + f.Buffer.B = append(f.Buffer.B, '+') + f.AppendFloatValue(imag(c)) + f.Buffer.B = append(f.Buffer.B, 'i') + }) +} + +func (f format) AppendPtr(u uint64) { + f._AppendPtrType(func(f format) { + if u == 0 { + // Append as nil + f.Buffer.B = append(f.Buffer.B, `nil`...) + } else { + // Append as hex number + f.Buffer.B = append(f.Buffer.B, `0x`...) + f.Buffer.B = strconv.AppendUint(f.Buffer.B, u, 16) + } + }) +} + +func (f format) AppendInterfaceOrReflect(i interface{}) { + if !f.AppendInterface(i) { + // Interface append failed, used reflected value + type + f.AppendReflectValue(reflect.ValueOf(i), reflect.TypeOf(i)) + } +} + +func (f format) AppendInterfaceOrReflectNext(v reflect.Value, t reflect.Type) { + // Check we haven't hit max + if f.AtMaxDepth() { + f.Buffer.B = append(f.Buffer.B, `...`...) + return + } + + // Incr the depth + f = f.IncrDepth() + + // Make actual call + f.AppendReflectOrInterface(v, t) +} + +func (f format) AppendReflectOrInterface(v reflect.Value, t reflect.Type) { + if !v.CanInterface() || + !f.AppendInterface(v.Interface()) { + // Interface append failed, use reflect + f.AppendReflectValue(v, t) + } +} + +func (f format) AppendInterface(i interface{}) bool { + switch i := i.(type) { + // Reflect types + case reflect.Type: + f.AppendReflectType(i) + case reflect.Value: + f.Buffer.B = append(f.Buffer.B, `reflect.Value`...) + f.Buffer.B = append(f.Buffer.B, '(') + f.Buffer.B = append(f.Buffer.B, i.String()...) + f.Buffer.B = append(f.Buffer.B, ')') + + // Bytes, runes and string types + case rune: + f.VType = `int32` + f.AppendRune(i) + case []rune: + f.VType = `[]int32` + f.AppendRunes(i) + case byte: + f.VType = `uint8` + f.AppendByte(i) + case []byte: + f.VType = `[]uint8` + f.AppendBytes(i) + case string: + f.VType = `string` + f.AppendString(i) + + // Int types + case int: + f.VType = `int` + f.AppendInt(int64(i)) + case int8: + f.VType = `int8` + f.AppendInt(int64(i)) + case int16: + f.VType = `int16` + f.AppendInt(int64(i)) + case int64: + f.VType = `int64` + f.AppendInt(int64(i)) + + // Uint types + case uint: + f.VType = `uint` + f.AppendUint(uint64(i)) + case uint16: + f.VType = `uint16` + f.AppendUint(uint64(i)) + case uint32: + f.VType = `uint32` + f.AppendUint(uint64(i)) + case uint64: + f.VType = `uint64` + f.AppendUint(uint64(i)) + + // Float types + case float32: + f.VType = `float32` + f.AppendFloat(float64(i)) + case float64: + f.VType = `float64` + f.AppendFloat(float64(i)) + + // Bool type + case bool: + f.VType = `bool` + f.AppendBool(i) + + // Complex types + case complex64: + f.VType = `complex64` + f.AppendComplex(complex128(i)) + case complex128: + f.VType = `complex128` + f.AppendComplex(complex128(i)) + + // Method types + case error: + return f._AppendMethodType(func() string { + return i.Error() + }, i) + case interface{ String() string }: + return f._AppendMethodType(func() string { + return i.String() + }, i) + + // No quick handler + default: + return false + } + + return true +} + +func (f format) AppendReflectType(t reflect.Type) { + switch f.VType = `reflect.Type`; { + case isNil(t) /* safer nil check */ : + f.AppendNil() + case f.Verbose(): + f.AppendType() + f.Buffer.B = append(f.Buffer.B, '(') + f.Buffer.B = append(f.Buffer.B, t.String()...) + f.Buffer.B = append(f.Buffer.B, ')') + default: + f.Buffer.B = append(f.Buffer.B, t.String()...) + } +} + +func (f format) AppendReflectValue(v reflect.Value, t reflect.Type) { + switch v.Kind() { + // String/byte types + case reflect.String: + f.VType = t.String() + f.AppendString(v.String()) + case reflect.Uint8: + f.VType = t.String() + f.AppendByte(byte(v.Uint())) + case reflect.Int32: + f.VType = t.String() + f.AppendRune(rune(v.Int())) + + // Float tpyes + case reflect.Float32, reflect.Float64: + f.VType = t.String() + f.AppendFloat(v.Float()) + + // Int types + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int64: + f.VType = t.String() + f.AppendInt(v.Int()) + + // Uint types + case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: + f.VType = t.String() + f.AppendUint(v.Uint()) + + // Complex types + case reflect.Complex64, reflect.Complex128: + f.VType = t.String() + f.AppendComplex(v.Complex()) + + // Bool type + case reflect.Bool: + f.VType = t.String() + f.AppendBool(v.Bool()) + + // Slice and array types + case reflect.Array: + f.AppendArray(v, t) + case reflect.Slice: + f.AppendSlice(v, t) + + // Map types + case reflect.Map: + f.AppendMap(v, t) + + // Struct types + case reflect.Struct: + f.AppendStruct(v, t) + + // Interface type + case reflect.Interface: + if v.IsNil() { + // Append nil ptr type + f.VType = t.String() + f.AppendNil() + } else { + // Append interface + v = v.Elem() + t = v.Type() + f.AppendReflectOrInterface(v, t) + } + + // Deref'able ptr type + case reflect.Ptr: + if v.IsNil() { + // Append nil ptr type + f.VType = t.String() + f.AppendNil() + } else { + // Deref to next level + f = f.IncrDerefs() + v, t = v.Elem(), t.Elem() + f.AppendReflectOrInterface(v, t) + } + + // 'raw' pointer types + case reflect.UnsafePointer, reflect.Func, reflect.Chan: + f.VType = t.String() + f.AppendPtr(uint64(v.Pointer())) + case reflect.Uintptr: + f.VType = t.String() + f.AppendPtr(v.Uint()) + + // Zero reflect value + case reflect.Invalid: + f.Buffer.B = append(f.Buffer.B, `nil`...) + + // All others + default: + f.VType = t.String() + f.AppendType() + } +} + +func (f format) AppendSlice(v reflect.Value, t reflect.Type) { + // Get slice value type + f.VType = t.String() + + if t.Elem().Kind() == reflect.Uint8 { + // This is a byte slice + f.AppendBytes(v.Bytes()) + return + } + + if v.IsNil() { + // Nil slice + f.AppendNil() + return + } + + if f.Verbose() { + // Append array with type information + f._AppendArrayTyped(func(f format) { + f.AppendArrayElems(v, t) + }) + } else { + // Simply append array as elems + f._AppendArray(func(f format) { + f.AppendArrayElems(v, t) + }) + } +} + +func (f format) AppendArray(v reflect.Value, t reflect.Type) { + // Get array value type + f.VType = t.String() + + if f.Verbose() { + // Append array with type information + f._AppendArrayTyped(func(f format) { + f.AppendArrayElems(v, t) + }) + } else { + // Simply append array as elems + f._AppendArray(func(f format) { + f.AppendArrayElems(v, t) + }) + } +} + +func (f format) AppendArrayElems(v reflect.Value, t reflect.Type) { + // Get no. elems + n := v.Len() + + // Get elem type + et := t.Elem() + + // Append values + for i := 0; i < n; i++ { + f.SetValue().AppendInterfaceOrReflectNext(v.Index(i), et) + f.Buffer.B = append(f.Buffer.B, ',') + } + + // Drop last comma + if n > 0 { + f.Buffer.Truncate(1) + } +} + +func (f format) AppendMap(v reflect.Value, t reflect.Type) { + // Get value type + f.VType = t.String() + + if v.IsNil() { + // Nil map -- no fields + f.AppendNil() + return + } + + // Append field formatted map fields + f._AppendFieldType(func(f format) { + f.AppendMapFields(v, t) + }) +} + +func (f format) AppendMapFields(v reflect.Value, t reflect.Type) { + // Get a map iterator + r := v.MapRange() + n := v.Len() + + // Get key/val types + kt := t.Key() + kv := t.Elem() + + // Iterate pairs + for r.Next() { + f.SetKey().AppendInterfaceOrReflectNext(r.Key(), kt) + f.Buffer.B = append(f.Buffer.B, '=') + f.SetValue().AppendInterfaceOrReflectNext(r.Value(), kv) + f.Buffer.B = append(f.Buffer.B, ' ') + } + + // Drop last space + if n > 0 { + f.Buffer.Truncate(1) + } +} + +func (f format) AppendStruct(v reflect.Value, t reflect.Type) { + // Get value type + f.VType = t.String() + + // Append field formatted struct fields + f._AppendFieldType(func(f format) { + f.AppendStructFields(v, t) + }) +} + +func (f format) AppendStructFields(v reflect.Value, t reflect.Type) { + // Get field no. + n := v.NumField() + + // Iterate struct fields + for i := 0; i < n; i++ { + vfield := v.Field(i) + tfield := t.Field(i) + + // Append field name + f.AppendStringKey(tfield.Name) + f.Buffer.B = append(f.Buffer.B, '=') + f.SetValue().AppendInterfaceOrReflectNext(vfield, tfield.Type) + + // Append separator + f.Buffer.B = append(f.Buffer.B, ' ') + } + + // Drop last space + if n > 0 { + f.Buffer.Truncate(1) + } +} + +func (f format) _AppendMethodType(method func() string, i interface{}) (ok bool) { + // Verbose -- no methods + if f.Verbose() { + return false + } + + // Catch nil type + if isNil(i) { + f.AppendNil() + return true + } + + // Catch any panics + defer func() { + if r := recover(); r != nil { + // DON'T recurse catchPanic() + if f.Panic() { + panic(r) + } + + // Attempt to decode panic into buf + f.Buffer.B = append(f.Buffer.B, `!{PANIC=`...) + f.SetPanic().AppendInterfaceOrReflect(r) + f.Buffer.B = append(f.Buffer.B, '}') + + // Ensure no further attempts + // to format after return + ok = true + } + }() + + // Get method result + result := method() + + switch { + // Append as key formatted + case f.Key(): + f.AppendStringKey(result) + + // Append as always quoted + case f.Value(): + f.AppendStringQuoted(result) + + // Append as-is + default: + f.Buffer.B = append(f.Buffer.B, result...) + } + + return true +} + +// _AppendPrimitiveType is a helper to append prefix/suffix for primitives (numbers/bools/bytes/runes). +func (f format) _AppendPrimitiveType(appendPrimitive func(format)) { + if f.Verbose() { + // Append value with type information + f._AppendPrimitiveTyped(appendPrimitive) + } else { + // Append simply as-is + appendPrimitive(f) + } +} + +// _AppendPrimitiveTyped is a helper to append prefix/suffix for primitives (numbers/bools/bytes/runes) with their types (if deref'd). +func (f format) _AppendPrimitiveTyped(appendPrimitive func(format)) { + if f.Derefs > 0 { + // Is deref'd, append type info + f.Buffer.B = append(f.Buffer.B, '(') + f.AppendType() + f.Buffer.WriteString(`)(`) + appendPrimitive(f) + f.Buffer.B = append(f.Buffer.B, ')') + } else { + // Simply append value + appendPrimitive(f) + } +} + +// _AppendPtrType is a helper to append prefix/suffix for ptr types (with type if necessary). +func (f format) _AppendPtrType(appendPtr func(format)) { + if f.Verbose() { + // Append value with type information + f.Buffer.B = append(f.Buffer.B, '(') + f.AppendType() + f.Buffer.WriteString(`)(`) + appendPtr(f) + f.Buffer.B = append(f.Buffer.B, ')') + } else { + // Append simply as-is + appendPtr(f) + } +} + +// _AppendArray is a helper to append prefix/suffix for array-types. +func (f format) _AppendArray(appendArray func(format)) { + f.Buffer.B = append(f.Buffer.B, '[') + appendArray(f) + f.Buffer.B = append(f.Buffer.B, ']') +} + +// _AppendArrayTyped is a helper to append prefix/suffix for array-types with their types. +func (f format) _AppendArrayTyped(appendArray func(format)) { + f.AppendType() + f.Buffer.B = append(f.Buffer.B, '{') + appendArray(f) + f.Buffer.B = append(f.Buffer.B, '}') +} + +// _AppendFields is a helper to append prefix/suffix for field-types (with type if necessary). +func (f format) _AppendFieldType(appendFields func(format)) { + if f.Verbose() { + f.AppendType() + } + f.Buffer.B = append(f.Buffer.B, '{') + appendFields(f) + f.Buffer.B = append(f.Buffer.B, '}') +} + +// byte2str returns 'c' as a string, escaping if necessary. +func byte2str(c byte) string { + switch c { + case '\a': + return `\a` + case '\b': + return `\b` + case '\f': + return `\f` + case '\n': + return `\n` + case '\r': + return `\r` + case '\t': + return `\t` + case '\v': + return `\v` + case '\'': + return `\\` + default: + if c < ' ' { + const hex = "0123456789abcdef" + return `\x` + + string(hex[c>>4]) + + string(hex[c&0xF]) + } + return string(c) + } +} diff --git a/vendor/codeberg.org/gruf/go-kv/format/formatter.go b/vendor/codeberg.org/gruf/go-kv/format/formatter.go new file mode 100644 index 000000000..fd8cf98df --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/format/formatter.go @@ -0,0 +1,349 @@ +package format + +import ( + "strconv" + "strings" + + "codeberg.org/gruf/go-byteutil" +) + +// Formatter allows configuring value and string formatting. +type Formatter struct { + // MaxDepth specifies the max depth of fields the formatter will iterate. + // Once max depth is reached, value will simply be formatted as "...". + // e.g. + // + // MaxDepth=1 + // type A struct{ + // Nested B + // } + // type B struct{ + // Nested C + // } + // type C struct{ + // Field string + // } + // + // Append(&buf, A{}) => {Nested={Nested={Field=...}}} + MaxDepth uint8 +} + +// Append will append formatted form of supplied values into 'buf'. +func (f *Formatter) Append(buf *byteutil.Buffer, v ...interface{}) { + fmt := format{Buffer: buf, Config: f} + for i := 0; i < len(v); i++ { + fmt.AppendInterfaceOrReflect(v[i]) + fmt.Buffer.B = append(fmt.Buffer.B, ' ') + } + if len(v) > 0 { + fmt.Buffer.Truncate(1) + } +} + +// Appendf will append the formatted string with supplied values into 'buf'. +// Supported format directives: +// - '{}' => format supplied arg, in place +// - '{0}' => format arg at index 0 of supplied, in place +// - '{:?}' => format supplied arg verbosely, in place +// - '{:k}' => format supplied arg as key, in place +// - '{:v}' => format supplied arg as value, in place +// +// To escape either of '{}' simply append an additional brace e.g. +// - '{{' => '{' +// - '}}' => '}' +// - '{{}}' => '{}' +// - '{{:?}}' => '{:?}' +// +// More formatting directives might be included in the future. +func (f *Formatter) Appendf(buf *byteutil.Buffer, s string, a ...interface{}) { + const ( + // ground state + modeNone = uint8(0) + + // prev reached '{' + modeOpen = uint8(1) + + // prev reached '}' + modeClose = uint8(2) + + // parsing directive index + modeIdx = uint8(3) + + // parsing directive operands + modeOp = uint8(4) + ) + + var ( + // mode is current parsing mode + mode uint8 + + // arg is the current arg index + arg int + + // carg is current directive-set arg index + carg int + + // last is the trailing cursor to see slice windows + last int + + // idx is the current index in 's' + idx int + + // fmt is the base argument formatter + fmt = format{ + Config: f, + Buffer: buf, + } + + // NOTE: these functions are defined here as function + // locals as it turned out to be better for performance + // doing it this way, than encapsulating their logic in + // some kind of parsing structure. Maybe if the parser + // was pooled along with the buffers it might work out + // better, but then it makes more internal functions i.e. + // .Append() .Appendf() less accessible outside package. + // + // Currently, passing '-gcflags "-l=4"' causes a not + // insignificant decrease in ns/op, which is likely due + // to more aggressive function inlining, which this + // function can obviously stand to benefit from :) + + // Str returns current string window slice, and updates + // the trailing cursor 'last' to current 'idx' + Str = func() string { + str := s[last:idx] + last = idx + return str + } + + // MoveUp moves the trailing cursor 'last' just past 'idx' + MoveUp = func() { + last = idx + 1 + } + + // MoveUpTo moves the trailing cursor 'last' either up to + // closest '}', or current 'idx', whichever is furthest. + // NOTE: by calling bytealg.IndexByteString() directly (and + // not the strconv pass-through, we shave-off complexity + // which allows this function to be inlined). + MoveUpTo = func() { + i := strings.IndexByte(s[idx:], '}') + if i >= 0 { + idx += i + } + MoveUp() + } + + // ParseIndex parses an integer from the current string + // window, updating 'last' to 'idx'. The string window + // is ASSUMED to contain only valid ASCII numbers. This + // only returns false if number exceeds platform int size + ParseIndex = func() bool { + var str string + + // Get current window + if str = Str(); len(str) < 1 { + return true + } + + // Index HAS to fit within platform integer size + if !(strconv.IntSize == 32 && (0 < len(s) && len(s) < 10)) || + !(strconv.IntSize == 64 && (0 < len(s) && len(s) < 19)) { + return false + } + + carg = 0 + + // Build integer from string + for i := 0; i < len(str); i++ { + carg = carg*10 + int(str[i]-'0') + } + + return true + } + + // ValidOp checks that for current ending idx, that a valid + // operand was achieved -- only 0, 1 are valid numbers. + ValidOp = func() bool { + diff := (idx - last) + last = idx + return diff < 2 + } + + // AppendArg will take either the directive-set, or + // iterated arg index, check within bounds of 'a' and + // append the that argument formatted to the buffer. + // On failure, it will append an error string + AppendArg = func() { + // Look for idx + if carg < 0 { + carg = arg + } + + // Incr idx + arg++ + + if carg < len(a) { + // Append formatted argument value + fmt.AppendInterfaceOrReflect(a[carg]) + } else { + // No argument found for index + fmt.Buffer.B = append(fmt.Buffer.B, `!{MISSING_ARG}`...) + } + } + + // Reset will reset the mode to ground, the flags + // to empty and parsed 'carg' to empty + Reset = func() { + mode = modeNone + fmt.CurDepth = 0 + fmt.Flags = 0 + fmt.VType = "" + fmt.Derefs = 0 + carg = -1 + } + ) + + for idx = 0; idx < len(s); idx++ { + // Get next char + c := s[idx] + + switch mode { + // Ground mode + case modeNone: + switch c { + case '{': + // Enter open mode + fmt.Buffer.B = append(fmt.Buffer.B, Str()...) + mode = modeOpen + MoveUp() + case '}': + // Enter close mode + fmt.Buffer.B = append(fmt.Buffer.B, Str()...) + mode = modeClose + MoveUp() + } + + // Encountered open '{' + case modeOpen: + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + // Starting index + mode = modeIdx + MoveUp() + case '{': + // Escaped bracket + fmt.Buffer.B = append(fmt.Buffer.B, '{') + mode = modeNone + MoveUp() + case '}': + // Format arg + AppendArg() + Reset() + MoveUp() + case ':': + // Starting operands + mode = modeOp + MoveUp() + default: + // Bad char, missing a close + fmt.Buffer.B = append(fmt.Buffer.B, `!{MISSING_CLOSE}`...) + mode = modeNone + MoveUpTo() + } + + // Encountered close '}' + case modeClose: + switch c { + case '}': + // Escaped close bracket + fmt.Buffer.B = append(fmt.Buffer.B, '}') + mode = modeNone + MoveUp() + default: + // Missing an open bracket + fmt.Buffer.B = append(fmt.Buffer.B, `!{MISSING_OPEN}`...) + mode = modeNone + MoveUp() + } + + // Preparing index + case modeIdx: + switch c { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + case ':': + if !ParseIndex() { + // Unable to parse an integer + fmt.Buffer.B = append(fmt.Buffer.B, `!{BAD_INDEX}`...) + mode = modeNone + MoveUpTo() + } else { + // Starting operands + mode = modeOp + MoveUp() + } + case '}': + if !ParseIndex() { + // Unable to parse an integer + fmt.Buffer.B = append(fmt.Buffer.B, `!{BAD_INDEX}`...) + } else { + // Format arg + AppendArg() + } + Reset() + MoveUp() + default: + // Not a valid index character + fmt.Buffer.B = append(fmt.Buffer.B, `!{BAD_INDEX}`...) + mode = modeNone + MoveUpTo() + } + + // Preparing operands + case modeOp: + switch c { + case 'k': + fmt.Flags |= IsKeyBit + case 'v': + fmt.Flags |= IsValBit + case '?': + fmt.Flags |= VboseBit + case '}': + if !ValidOp() { + // Bad operands parsed + fmt.Buffer.B = append(fmt.Buffer.B, `!{BAD_OPERAND}`...) + } else { + // Format arg + AppendArg() + } + Reset() + MoveUp() + default: + // Not a valid operand char + fmt.Buffer.B = append(fmt.Buffer.B, `!{BAD_OPERAND}`...) + Reset() + MoveUpTo() + } + } + } + + // Append any remaining + fmt.Buffer.B = append(fmt.Buffer.B, s[last:]...) +} + +// formatter is the default formatter instance. +var formatter = Formatter{ + MaxDepth: 10, +} + +// Append will append formatted form of supplied values into 'buf' using default formatter. +// See Formatter.Append() for more documentation. +func Append(buf *byteutil.Buffer, v ...interface{}) { + formatter.Append(buf, v...) +} + +// Appendf will append the formatted string with supplied values into 'buf' using default formatter. +// See Formatter.Appendf() for more documentation. +func Appendf(buf *byteutil.Buffer, s string, a ...interface{}) { + formatter.Appendf(buf, s, a...) +} diff --git a/vendor/codeberg.org/gruf/go-kv/format/util.go b/vendor/codeberg.org/gruf/go-kv/format/util.go new file mode 100644 index 000000000..c4c42329e --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/format/util.go @@ -0,0 +1,56 @@ +package format + +import ( + "strings" + "unsafe" +) + +// ContainsSpaceOrTab checks if "s" contains space or tabs. +func ContainsSpaceOrTab(s string) bool { + if i := strings.IndexByte(s, ' '); i != -1 { + return true // note using indexbyte as it is ASM. + } else if i := strings.IndexByte(s, '\t'); i != -1 { + return true + } + return false +} + +// ContainsDoubleQuote checks if "s" contains a double quote. +func ContainsDoubleQuote(s string) bool { + return (strings.IndexByte(s, '"') != -1) +} + +// AppendEscape will append 's' to 'dst' and escape any double quotes. +func AppendEscape(dst []byte, str string) []byte { + var delim bool + for i := range str { + if str[i] == '\\' && !delim { + // Set delim flag + delim = true + continue + } else if str[i] == '"' && !delim { + // Append escaped double quote + dst = append(dst, `\"`...) + continue + } else if delim { + // Append skipped slash + dst = append(dst, `\`...) + delim = false + } + + // Append char as-is + dst = append(dst, str[i]) + } + return dst +} + +// isNil will safely check if 'v' is nil without dealing with weird Go interface nil bullshit. +func isNil(i interface{}) bool { + type eface struct{ _type, data unsafe.Pointer } //nolint + return (*(*eface)(unsafe.Pointer(&i))).data == nil //nolint +} + +// b2s converts a byteslice to string without allocation. +func b2s(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} diff --git a/vendor/codeberg.org/gruf/go-kv/util.go b/vendor/codeberg.org/gruf/go-kv/util.go new file mode 100644 index 000000000..a9526bf3d --- /dev/null +++ b/vendor/codeberg.org/gruf/go-kv/util.go @@ -0,0 +1,71 @@ +package kv + +import ( + "strconv" + + "codeberg.org/gruf/go-byteutil" + "codeberg.org/gruf/go-kv/format" +) + +// appendQuoteKey will append and escape/quote a formatted key string. +func appendQuoteKey(buf *byteutil.Buffer, str string) { + switch { + case !strconv.CanBackquote(str): + // Append quoted and escaped string + buf.B = strconv.AppendQuote(buf.B, str) + case format.ContainsDoubleQuote(str): + // Double quote and escape string + buf.B = append(buf.B, '"') + buf.B = format.AppendEscape(buf.B, str) + buf.B = append(buf.B, '"') + case len(str) < 1 || format.ContainsSpaceOrTab(str): + // Double quote this string as-is + buf.WriteString(`"` + str + `"`) + default: + // Append string as-is + buf.WriteString(str) + } +} + +// appendQuoteValue will append and escape/quote a formatted value string. +func appendQuoteValue(buf *byteutil.Buffer, str string) { + switch { + case !strconv.CanBackquote(str): + // Append quoted and escaped string + buf.B = strconv.AppendQuote(buf.B, str) + return + case !doubleQuoted(str): + if format.ContainsDoubleQuote(str) { + // Double quote and escape string + buf.B = append(buf.B, '"') + buf.B = format.AppendEscape(buf.B, str) + buf.B = append(buf.B, '"') + return + } else if format.ContainsSpaceOrTab(str) { + // Double quote this string as-is + buf.WriteString(`"` + str + `"`) + return + } + } + + // Append string as-is + buf.WriteString(str) +} + +// doubleQuoted will return whether 'str' is double quoted. +func doubleQuoted(str string) bool { + if len(str) < 2 || + str[0] != '"' || str[len(str)-1] != '"' { + return false + } + var delim bool + for i := len(str) - 2; i >= 0; i-- { + switch str[i] { + case '\\': + delim = !delim + default: + return !delim + } + } + return !delim +} diff --git a/vendor/codeberg.org/gruf/go-logger/v2/LICENSE b/vendor/codeberg.org/gruf/go-logger/v2/LICENSE new file mode 100644 index 000000000..e4163ae35 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-logger/v2/LICENSE @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) 2022 gruf + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/codeberg.org/gruf/go-logger/v2/level/levels.go b/vendor/codeberg.org/gruf/go-logger/v2/level/levels.go new file mode 100644 index 000000000..1804bdb23 --- /dev/null +++ b/vendor/codeberg.org/gruf/go-logger/v2/level/levels.go @@ -0,0 +1,49 @@ +package level + +// LEVEL defines a level of logging. +type LEVEL uint8 + +// Default levels of logging. +const ( + UNSET LEVEL = 0 + PANIC LEVEL = 1 + FATAL LEVEL = 50 + ERROR LEVEL = 100 + WARN LEVEL = 150 + INFO LEVEL = 200 + DEBUG LEVEL = 250 + TRACE LEVEL = 254 + ALL LEVEL = ^LEVEL(0) +) + +// CanLog returns whether an incoming log of 'lvl' can be logged against receiving level. +func (loglvl LEVEL) CanLog(lvl LEVEL) bool { + return loglvl > lvl +} + +// Levels defines a mapping of log LEVELs to formatted level strings. +type Levels [int(ALL) + 1]string + +// Default returns the default set of log levels. +func Default() Levels { + return Levels{ + TRACE: "TRACE", + DEBUG: "DEBUG", + INFO: "INFO", + WARN: "WARN", + ERROR: "ERROR", + FATAL: "FATAL", + PANIC: "PANIC", + + // we set these just so that + // it can be debugged when someone + // attempts to log with ALL/UNSET + ALL: "{all}", + UNSET: "{unset}", + } +} + +// Get fetches the level string for the provided value. +func (l Levels) Get(lvl LEVEL) string { + return l[int(lvl)] +} |