Initial commit
This commit is contained in:
160
vendor/github.com/cockroachdb/errors/errbase/decode.go
generated
vendored
Normal file
160
vendor/github.com/cockroachdb/errors/errbase/decode.go
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2019 The Cockroach Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
package errbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cockroachdb/errors/errorspb"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/gogo/protobuf/types"
|
||||
)
|
||||
|
||||
// DecodeError decodes an error.
|
||||
func DecodeError(ctx context.Context, enc EncodedError) error {
|
||||
if w := enc.GetWrapper(); w != nil {
|
||||
return decodeWrapper(ctx, w)
|
||||
}
|
||||
return decodeLeaf(ctx, enc.GetLeaf())
|
||||
}
|
||||
|
||||
func decodeLeaf(ctx context.Context, enc *errorspb.EncodedErrorLeaf) error {
|
||||
// In case there is a detailed payload, decode it.
|
||||
var payload proto.Message
|
||||
if enc.Details.FullDetails != nil {
|
||||
var d types.DynamicAny
|
||||
err := types.UnmarshalAny(enc.Details.FullDetails, &d)
|
||||
if err != nil {
|
||||
// It's OK if we can't decode. We'll use
|
||||
// the opaque type below.
|
||||
warningFn(ctx, "error while unmarshalling error: %+v", err)
|
||||
} else {
|
||||
payload = d.Message
|
||||
}
|
||||
}
|
||||
|
||||
// Do we have a leaf decoder for this type?
|
||||
typeKey := TypeKey(enc.Details.ErrorTypeMark.FamilyName)
|
||||
if decoder, ok := leafDecoders[typeKey]; ok {
|
||||
// Yes, use it.
|
||||
genErr := decoder(ctx, enc.Message, enc.Details.ReportablePayload, payload)
|
||||
if genErr != nil {
|
||||
// Decoding succeeded. Use this.
|
||||
return genErr
|
||||
}
|
||||
// Decoding failed, we'll drop through to opaqueLeaf{} below.
|
||||
} else {
|
||||
// Shortcut for non-registered proto-encodable error types:
|
||||
// if it already implements `error`, it's good to go.
|
||||
if e, ok := payload.(error); ok {
|
||||
// yes: we're done!
|
||||
return e
|
||||
}
|
||||
}
|
||||
|
||||
// No decoder and no error type: we'll keep what we received and
|
||||
// make it ready to re-encode exactly (if the error leaves over the
|
||||
// network again).
|
||||
return &opaqueLeaf{
|
||||
msg: enc.Message,
|
||||
details: enc.Details,
|
||||
}
|
||||
}
|
||||
|
||||
func decodeWrapper(ctx context.Context, enc *errorspb.EncodedWrapper) error {
|
||||
// First decode the cause.
|
||||
cause := DecodeError(ctx, enc.Cause)
|
||||
|
||||
// In case there is a detailed payload, decode it.
|
||||
var payload proto.Message
|
||||
if enc.Details.FullDetails != nil {
|
||||
var d types.DynamicAny
|
||||
err := types.UnmarshalAny(enc.Details.FullDetails, &d)
|
||||
if err != nil {
|
||||
// It's OK if we can't decode. We'll use
|
||||
// the opaque type below.
|
||||
warningFn(ctx, "error while unmarshalling wrapper error: %+v", err)
|
||||
} else {
|
||||
payload = d.Message
|
||||
}
|
||||
}
|
||||
|
||||
// Do we have a wrapper decoder for this?
|
||||
typeKey := TypeKey(enc.Details.ErrorTypeMark.FamilyName)
|
||||
if decoder, ok := decoders[typeKey]; ok {
|
||||
// Yes, use it.
|
||||
genErr := decoder(ctx, cause, enc.MessagePrefix, enc.Details.ReportablePayload, payload)
|
||||
if genErr != nil {
|
||||
// Decoding succeeded. Use this.
|
||||
return genErr
|
||||
}
|
||||
// Decoding failed, we'll drop through to opaqueWrapper{} below.
|
||||
}
|
||||
|
||||
// Otherwise, preserve all details about the original object.
|
||||
return &opaqueWrapper{
|
||||
cause: cause,
|
||||
prefix: enc.MessagePrefix,
|
||||
details: enc.Details,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterLeafDecoder can be used to register new leaf error types to
|
||||
// the library. Registered types will be decoded using their own
|
||||
// Go type when an error is decoded. Wrappers that have not been
|
||||
// registered will be decoded using the opaqueLeaf type.
|
||||
//
|
||||
// Note: if the error type has been migrated from a previous location
|
||||
// or a different type, ensure that RegisterTypeMigration() was called
|
||||
// prior to RegisterLeafDecoder().
|
||||
func RegisterLeafDecoder(theType TypeKey, decoder LeafDecoder) {
|
||||
if decoder == nil {
|
||||
delete(leafDecoders, theType)
|
||||
} else {
|
||||
leafDecoders[theType] = decoder
|
||||
}
|
||||
}
|
||||
|
||||
// LeafDecoder is to be provided (via RegisterLeafDecoder above)
|
||||
// by additional wrapper types not yet known to this library.
|
||||
// A nil return indicates that decoding was not successful.
|
||||
type LeafDecoder = func(ctx context.Context, msg string, safeDetails []string, payload proto.Message) error
|
||||
|
||||
// registry for RegisterLeafDecoder.
|
||||
var leafDecoders = map[TypeKey]LeafDecoder{}
|
||||
|
||||
// RegisterWrapperDecoder can be used to register new wrapper types to
|
||||
// the library. Registered wrappers will be decoded using their own
|
||||
// Go type when an error is decoded. Wrappers that have not been
|
||||
// registered will be decoded using the opaqueWrapper type.
|
||||
//
|
||||
// Note: if the error type has been migrated from a previous location
|
||||
// or a different type, ensure that RegisterTypeMigration() was called
|
||||
// prior to RegisterWrapperDecoder().
|
||||
func RegisterWrapperDecoder(theType TypeKey, decoder WrapperDecoder) {
|
||||
if decoder == nil {
|
||||
delete(decoders, theType)
|
||||
} else {
|
||||
decoders[theType] = decoder
|
||||
}
|
||||
}
|
||||
|
||||
// WrapperDecoder is to be provided (via RegisterWrapperDecoder above)
|
||||
// by additional wrapper types not yet known to this library.
|
||||
// A nil return indicates that decoding was not successful.
|
||||
type WrapperDecoder = func(ctx context.Context, cause error, msgPrefix string, safeDetails []string, payload proto.Message) error
|
||||
|
||||
// registry for RegisterWrapperType.
|
||||
var decoders = map[TypeKey]WrapperDecoder{}
|
||||
Reference in New Issue
Block a user