mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 23:12:26 -06:00 
			
		
		
		
	* Add SQLite support, fix un-thread-safe DB caches, small performance fixes Signed-off-by: kim (grufwub) <grufwub@gmail.com> * add SQLite licenses to README Signed-off-by: kim (grufwub) <grufwub@gmail.com> * appease the linter, and fix my dumbass-ery Signed-off-by: kim (grufwub) <grufwub@gmail.com> * make requested changes Signed-off-by: kim (grufwub) <grufwub@gmail.com> * add back comment Signed-off-by: kim (grufwub) <grufwub@gmail.com>
		
			
				
	
	
		
			187 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2018 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 xerrors
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strings"
 | 
						|
	"unicode"
 | 
						|
	"unicode/utf8"
 | 
						|
 | 
						|
	"golang.org/x/xerrors/internal"
 | 
						|
)
 | 
						|
 | 
						|
const percentBangString = "%!"
 | 
						|
 | 
						|
// Errorf formats according to a format specifier and returns the string as a
 | 
						|
// value that satisfies error.
 | 
						|
//
 | 
						|
// The returned error includes the file and line number of the caller when
 | 
						|
// formatted with additional detail enabled. If the last argument is an error
 | 
						|
// the returned error's Format method will return it if the format string ends
 | 
						|
// with ": %s", ": %v", or ": %w". If the last argument is an error and the
 | 
						|
// format string ends with ": %w", the returned error implements an Unwrap
 | 
						|
// method returning it.
 | 
						|
//
 | 
						|
// If the format specifier includes a %w verb with an error operand in a
 | 
						|
// position other than at the end, the returned error will still implement an
 | 
						|
// Unwrap method returning the operand, but the error's Format method will not
 | 
						|
// return the wrapped error.
 | 
						|
//
 | 
						|
// It is invalid to include more than one %w verb or to supply it with an
 | 
						|
// operand that does not implement the error interface. The %w verb is otherwise
 | 
						|
// a synonym for %v.
 | 
						|
func Errorf(format string, a ...interface{}) error {
 | 
						|
	format = formatPlusW(format)
 | 
						|
	// Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
 | 
						|
	wrap := strings.HasSuffix(format, ": %w")
 | 
						|
	idx, format2, ok := parsePercentW(format)
 | 
						|
	percentWElsewhere := !wrap && idx >= 0
 | 
						|
	if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
 | 
						|
		err := errorAt(a, len(a)-1)
 | 
						|
		if err == nil {
 | 
						|
			return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
 | 
						|
		}
 | 
						|
		// TODO: this is not entirely correct. The error value could be
 | 
						|
		// printed elsewhere in format if it mixes numbered with unnumbered
 | 
						|
		// substitutions. With relatively small changes to doPrintf we can
 | 
						|
		// have it optionally ignore extra arguments and pass the argument
 | 
						|
		// list in its entirety.
 | 
						|
		msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
 | 
						|
		frame := Frame{}
 | 
						|
		if internal.EnableTrace {
 | 
						|
			frame = Caller(1)
 | 
						|
		}
 | 
						|
		if wrap {
 | 
						|
			return &wrapError{msg, err, frame}
 | 
						|
		}
 | 
						|
		return &noWrapError{msg, err, frame}
 | 
						|
	}
 | 
						|
	// Support %w anywhere.
 | 
						|
	// TODO: don't repeat the wrapped error's message when %w occurs in the middle.
 | 
						|
	msg := fmt.Sprintf(format2, a...)
 | 
						|
	if idx < 0 {
 | 
						|
		return &noWrapError{msg, nil, Caller(1)}
 | 
						|
	}
 | 
						|
	err := errorAt(a, idx)
 | 
						|
	if !ok || err == nil {
 | 
						|
		// Too many %ws or argument of %w is not an error. Approximate the Go
 | 
						|
		// 1.13 fmt.Errorf message.
 | 
						|
		return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
 | 
						|
	}
 | 
						|
	frame := Frame{}
 | 
						|
	if internal.EnableTrace {
 | 
						|
		frame = Caller(1)
 | 
						|
	}
 | 
						|
	return &wrapError{msg, err, frame}
 | 
						|
}
 | 
						|
 | 
						|
func errorAt(args []interface{}, i int) error {
 | 
						|
	if i < 0 || i >= len(args) {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	err, ok := args[i].(error)
 | 
						|
	if !ok {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
// formatPlusW is used to avoid the vet check that will barf at %w.
 | 
						|
func formatPlusW(s string) string {
 | 
						|
	return s
 | 
						|
}
 | 
						|
 | 
						|
// Return the index of the only %w in format, or -1 if none.
 | 
						|
// Also return a rewritten format string with %w replaced by %v, and
 | 
						|
// false if there is more than one %w.
 | 
						|
// TODO: handle "%[N]w".
 | 
						|
func parsePercentW(format string) (idx int, newFormat string, ok bool) {
 | 
						|
	// Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
 | 
						|
	idx = -1
 | 
						|
	ok = true
 | 
						|
	n := 0
 | 
						|
	sz := 0
 | 
						|
	var isW bool
 | 
						|
	for i := 0; i < len(format); i += sz {
 | 
						|
		if format[i] != '%' {
 | 
						|
			sz = 1
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		// "%%" is not a format directive.
 | 
						|
		if i+1 < len(format) && format[i+1] == '%' {
 | 
						|
			sz = 2
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		sz, isW = parsePrintfVerb(format[i:])
 | 
						|
		if isW {
 | 
						|
			if idx >= 0 {
 | 
						|
				ok = false
 | 
						|
			} else {
 | 
						|
				idx = n
 | 
						|
			}
 | 
						|
			// "Replace" the last character, the 'w', with a 'v'.
 | 
						|
			p := i + sz - 1
 | 
						|
			format = format[:p] + "v" + format[p+1:]
 | 
						|
		}
 | 
						|
		n++
 | 
						|
	}
 | 
						|
	return idx, format, ok
 | 
						|
}
 | 
						|
 | 
						|
// Parse the printf verb starting with a % at s[0].
 | 
						|
// Return how many bytes it occupies and whether the verb is 'w'.
 | 
						|
func parsePrintfVerb(s string) (int, bool) {
 | 
						|
	// Assume only that the directive is a sequence of non-letters followed by a single letter.
 | 
						|
	sz := 0
 | 
						|
	var r rune
 | 
						|
	for i := 1; i < len(s); i += sz {
 | 
						|
		r, sz = utf8.DecodeRuneInString(s[i:])
 | 
						|
		if unicode.IsLetter(r) {
 | 
						|
			return i + sz, r == 'w'
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return len(s), false
 | 
						|
}
 | 
						|
 | 
						|
type noWrapError struct {
 | 
						|
	msg   string
 | 
						|
	err   error
 | 
						|
	frame Frame
 | 
						|
}
 | 
						|
 | 
						|
func (e *noWrapError) Error() string {
 | 
						|
	return fmt.Sprint(e)
 | 
						|
}
 | 
						|
 | 
						|
func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
 | 
						|
 | 
						|
func (e *noWrapError) FormatError(p Printer) (next error) {
 | 
						|
	p.Print(e.msg)
 | 
						|
	e.frame.Format(p)
 | 
						|
	return e.err
 | 
						|
}
 | 
						|
 | 
						|
type wrapError struct {
 | 
						|
	msg   string
 | 
						|
	err   error
 | 
						|
	frame Frame
 | 
						|
}
 | 
						|
 | 
						|
func (e *wrapError) Error() string {
 | 
						|
	return fmt.Sprint(e)
 | 
						|
}
 | 
						|
 | 
						|
func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
 | 
						|
 | 
						|
func (e *wrapError) FormatError(p Printer) (next error) {
 | 
						|
	p.Print(e.msg)
 | 
						|
	e.frame.Format(p)
 | 
						|
	return e.err
 | 
						|
}
 | 
						|
 | 
						|
func (e *wrapError) Unwrap() error {
 | 
						|
	return e.err
 | 
						|
}
 |