OSDN Git Service

new repo
[bytom/vapor.git] / vendor / google.golang.org / grpc / status / status.go
1 /*
2  *
3  * Copyright 2017 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 // Package status implements errors returned by gRPC.  These errors are
20 // serialized and transmitted on the wire between server and client, and allow
21 // for additional data to be transmitted via the Details field in the status
22 // proto.  gRPC service handlers should return an error created by this
23 // package, and gRPC clients should expect a corresponding error to be
24 // returned from the RPC call.
25 //
26 // This package upholds the invariants that a non-nil error may not
27 // contain an OK code, and an OK code must result in a nil error.
28 package status
29
30 import (
31         "errors"
32         "fmt"
33
34         "github.com/golang/protobuf/proto"
35         "github.com/golang/protobuf/ptypes"
36         spb "google.golang.org/genproto/googleapis/rpc/status"
37         "google.golang.org/grpc/codes"
38 )
39
40 // statusError is an alias of a status proto.  It implements error and Status,
41 // and a nil statusError should never be returned by this package.
42 type statusError spb.Status
43
44 func (se *statusError) Error() string {
45         p := (*spb.Status)(se)
46         return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
47 }
48
49 func (se *statusError) status() *Status {
50         return &Status{s: (*spb.Status)(se)}
51 }
52
53 // Status represents an RPC status code, message, and details.  It is immutable
54 // and should be created with New, Newf, or FromProto.
55 type Status struct {
56         s *spb.Status
57 }
58
59 // Code returns the status code contained in s.
60 func (s *Status) Code() codes.Code {
61         if s == nil || s.s == nil {
62                 return codes.OK
63         }
64         return codes.Code(s.s.Code)
65 }
66
67 // Message returns the message contained in s.
68 func (s *Status) Message() string {
69         if s == nil || s.s == nil {
70                 return ""
71         }
72         return s.s.Message
73 }
74
75 // Proto returns s's status as an spb.Status proto message.
76 func (s *Status) Proto() *spb.Status {
77         if s == nil {
78                 return nil
79         }
80         return proto.Clone(s.s).(*spb.Status)
81 }
82
83 // Err returns an immutable error representing s; returns nil if s.Code() is
84 // OK.
85 func (s *Status) Err() error {
86         if s.Code() == codes.OK {
87                 return nil
88         }
89         return (*statusError)(s.s)
90 }
91
92 // New returns a Status representing c and msg.
93 func New(c codes.Code, msg string) *Status {
94         return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
95 }
96
97 // Newf returns New(c, fmt.Sprintf(format, a...)).
98 func Newf(c codes.Code, format string, a ...interface{}) *Status {
99         return New(c, fmt.Sprintf(format, a...))
100 }
101
102 // Error returns an error representing c and msg.  If c is OK, returns nil.
103 func Error(c codes.Code, msg string) error {
104         return New(c, msg).Err()
105 }
106
107 // Errorf returns Error(c, fmt.Sprintf(format, a...)).
108 func Errorf(c codes.Code, format string, a ...interface{}) error {
109         return Error(c, fmt.Sprintf(format, a...))
110 }
111
112 // ErrorProto returns an error representing s.  If s.Code is OK, returns nil.
113 func ErrorProto(s *spb.Status) error {
114         return FromProto(s).Err()
115 }
116
117 // FromProto returns a Status representing s.
118 func FromProto(s *spb.Status) *Status {
119         return &Status{s: proto.Clone(s).(*spb.Status)}
120 }
121
122 // FromError returns a Status representing err if it was produced from this
123 // package, otherwise it returns nil, false.
124 func FromError(err error) (s *Status, ok bool) {
125         if err == nil {
126                 return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true
127         }
128         if s, ok := err.(*statusError); ok {
129                 return s.status(), true
130         }
131         return nil, false
132 }
133
134 // WithDetails returns a new status with the provided details messages appended to the status.
135 // If any errors are encountered, it returns nil and the first error encountered.
136 func (s *Status) WithDetails(details ...proto.Message) (*Status, error) {
137         if s.Code() == codes.OK {
138                 return nil, errors.New("no error details for status with code OK")
139         }
140         // s.Code() != OK implies that s.Proto() != nil.
141         p := s.Proto()
142         for _, detail := range details {
143                 any, err := ptypes.MarshalAny(detail)
144                 if err != nil {
145                         return nil, err
146                 }
147                 p.Details = append(p.Details, any)
148         }
149         return &Status{s: p}, nil
150 }
151
152 // Details returns a slice of details messages attached to the status.
153 // If a detail cannot be decoded, the error is returned in place of the detail.
154 func (s *Status) Details() []interface{} {
155         if s == nil || s.s == nil {
156                 return nil
157         }
158         details := make([]interface{}, 0, len(s.s.Details))
159         for _, any := range s.s.Details {
160                 detail := &ptypes.DynamicAny{}
161                 if err := ptypes.UnmarshalAny(any, detail); err != nil {
162                         details = append(details, err)
163                         continue
164                 }
165                 details = append(details, detail.Message)
166         }
167         return details
168 }