1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package errors implements functions to manipulate errors. 6package errors 7 8import ( 9 "errors" 10 "fmt" 11 12 "google.golang.org/protobuf/internal/detrand" 13) 14 15// Error is a sentinel matching all errors produced by this package. 16var Error = errors.New("protobuf error") 17 18// New formats a string according to the format specifier and arguments and 19// returns an error that has a "proto" prefix. 20func New(f string, x ...interface{}) error { 21 return &prefixError{s: format(f, x...)} 22} 23 24type prefixError struct{ s string } 25 26var prefix = func() string { 27 // Deliberately introduce instability into the error message string to 28 // discourage users from performing error string comparisons. 29 if detrand.Bool() { 30 return "proto: " // use non-breaking spaces (U+00a0) 31 } else { 32 return "proto: " // use regular spaces (U+0020) 33 } 34}() 35 36func (e *prefixError) Error() string { 37 return prefix + e.s 38} 39 40func (e *prefixError) Unwrap() error { 41 return Error 42} 43 44// Wrap returns an error that has a "proto" prefix, the formatted string described 45// by the format specifier and arguments, and a suffix of err. The error wraps err. 46func Wrap(err error, f string, x ...interface{}) error { 47 return &wrapError{ 48 s: format(f, x...), 49 err: err, 50 } 51} 52 53type wrapError struct { 54 s string 55 err error 56} 57 58func (e *wrapError) Error() string { 59 return format("%v%v: %v", prefix, e.s, e.err) 60} 61 62func (e *wrapError) Unwrap() error { 63 return e.err 64} 65 66func (e *wrapError) Is(target error) bool { 67 return target == Error 68} 69 70func format(f string, x ...interface{}) string { 71 // avoid "proto: " prefix when chaining 72 for i := 0; i < len(x); i++ { 73 switch e := x[i].(type) { 74 case *prefixError: 75 x[i] = e.s 76 case *wrapError: 77 x[i] = format("%v: %v", e.s, e.err) 78 } 79 } 80 return fmt.Sprintf(f, x...) 81} 82 83func InvalidUTF8(name string) error { 84 return New("field %v contains invalid UTF-8", name) 85} 86 87func RequiredNotSet(name string) error { 88 return New("required field %v not set", name) 89} 90