Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(773)

Side by Side Diff: luci_config/server/cfgclient/textproto/resolver.go

Issue 2963503003: [errors] Greatly simplify common/errors package. (Closed)
Patch Set: fix nits Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « luci_config/server/cfgclient/resolver.go ('k') | lucictx/lucictx.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // Package textproto implements a textproto config service Resolver. 5 // Package textproto implements a textproto config service Resolver.
6 // 6 //
7 // It uses the "luci-go" text protobuf multi-line extension. For more 7 // It uses the "luci-go" text protobuf multi-line extension. For more
8 // information, see: github.com/luci/luci-go/common/proto 8 // information, see: github.com/luci/luci-go/common/proto
9 // 9 //
10 // The textproto protobuf Resolver internally formats its content as a binary 10 // The textproto protobuf Resolver internally formats its content as a binary
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 // var out []*MyProtoMessages 74 // var out []*MyProtoMessages
75 // TextProtoSlice(&out) 75 // TextProtoSlice(&out)
76 func Slice(out interface{}) interface { 76 func Slice(out interface{}) interface {
77 cfgclient.MultiResolver 77 cfgclient.MultiResolver
78 cfgclient.FormattingResolver 78 cfgclient.FormattingResolver
79 } { 79 } {
80 r := resolver{} 80 r := resolver{}
81 81
82 v := reflect.ValueOf(out) 82 v := reflect.ValueOf(out)
83 if !r.loadMulti(v) { 83 if !r.loadMulti(v) {
84 » » panic(errors.Reason("%(type)s is not a pointer to a slice of pro tobuf message types").D("type", v.Type()).Err()) 84 » » panic(errors.Reason("%s is not a pointer to a slice of protobuf message types", v.Type()).Err())
85 } 85 }
86 return &r 86 return &r
87 } 87 }
88 88
89 type resolver struct { 89 type resolver struct {
90 messageName string 90 messageName string
91 91
92 single proto.Message 92 single proto.Message
93 singleType reflect.Type 93 singleType reflect.Type
94 94
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 137 }
138 r.multiDest.Index(i).Set(msgV) 138 r.multiDest.Index(i).Set(msgV)
139 return nil 139 return nil
140 } 140 }
141 141
142 func (r *resolver) resolveItem(out proto.Message, content string, format string) error { 142 func (r *resolver) resolveItem(out proto.Message, content string, format string) error {
143 switch format { 143 switch format {
144 case "": 144 case "":
145 // Not formatted (text protobuf). 145 // Not formatted (text protobuf).
146 if err := luciProto.UnmarshalTextML(content, out); err != nil { 146 if err := luciProto.UnmarshalTextML(content, out); err != nil {
147 » » » return errors.Annotate(err).Reason("failed to unmarshal text protobuf").Err() 147 » » » return errors.Annotate(err, "failed to unmarshal text pr otobuf").Err()
148 } 148 }
149 return nil 149 return nil
150 150
151 case BinaryFormat: 151 case BinaryFormat:
152 if err := parseBinaryContent(content, out); err != nil { 152 if err := parseBinaryContent(content, out); err != nil {
153 » » » return errors.Annotate(err).Reason("failed to unmarshal binary protobuf").Err() 153 » » » return errors.Annotate(err, "failed to unmarshal binary protobuf").Err()
154 } 154 }
155 return nil 155 return nil
156 156
157 default: 157 default:
158 » » return errors.Reason("unsupported content format: %(format)q").D ("format", format).Err() 158 » » return errors.Reason("unsupported content format: %q", format).E rr()
159 } 159 }
160 } 160 }
161 161
162 func (r *resolver) Format() backend.FormatSpec { 162 func (r *resolver) Format() backend.FormatSpec {
163 return backend.FormatSpec{BinaryFormat, r.messageName} 163 return backend.FormatSpec{BinaryFormat, r.messageName}
164 } 164 }
165 165
166 // Formatter is a cfgclient.Formatter implementation bound to a specific 166 // Formatter is a cfgclient.Formatter implementation bound to a specific
167 // protobuf message. 167 // protobuf message.
168 // 168 //
169 // It takes a text protobuf representation of that message as input and returns 169 // It takes a text protobuf representation of that message as input and returns
170 // a binary protobuf representation as output. 170 // a binary protobuf representation as output.
171 type Formatter struct{} 171 type Formatter struct{}
172 172
173 // FormatItem implements cfgclient.Formatter. 173 // FormatItem implements cfgclient.Formatter.
174 func (f *Formatter) FormatItem(c, fd string) (string, error) { 174 func (f *Formatter) FormatItem(c, fd string) (string, error) {
175 archetype := proto.MessageType(fd) 175 archetype := proto.MessageType(fd)
176 if archetype == nil { 176 if archetype == nil {
177 » » return "", errors.Reason("unknown proto.Message type %(type)q in formatter data"). 177 » » return "", errors.Reason("unknown proto.Message type %q in forma tter data", fd).Err()
178 » » » D("type", fd).Err()
179 } 178 }
180 msg := archetypeMessage(archetype) 179 msg := archetypeMessage(archetype)
181 180
182 // Convert from config to protobuf. 181 // Convert from config to protobuf.
183 if err := luciProto.UnmarshalTextML(c, msg); err != nil { 182 if err := luciProto.UnmarshalTextML(c, msg); err != nil {
184 » » return "", errors.Annotate(err).Reason("failed to unmarshal text protobuf content").Err() 183 » » return "", errors.Annotate(err, "failed to unmarshal text protob uf content").Err()
185 } 184 }
186 185
187 // Binary format. 186 // Binary format.
188 bc, err := makeBinaryContent(msg) 187 bc, err := makeBinaryContent(msg)
189 if err != nil { 188 if err != nil {
190 » » return "", errors.Annotate(err).Err() 189 » » return "", errors.Annotate(err, "").Err()
191 } 190 }
192 return bc, nil 191 return bc, nil
193 } 192 }
194 193
195 // t is a pointer to a proto.Message instance. 194 // t is a pointer to a proto.Message instance.
196 func archetypeInstance(t reflect.Type) reflect.Value { 195 func archetypeInstance(t reflect.Type) reflect.Value {
197 return reflect.New(t.Elem()) 196 return reflect.New(t.Elem())
198 } 197 }
199 198
200 func archetypeMessage(t reflect.Type) proto.Message { 199 func archetypeMessage(t reflect.Type) proto.Message {
201 return archetypeInstance(t).Interface().(proto.Message) 200 return archetypeInstance(t).Interface().(proto.Message)
202 } 201 }
203 202
204 // makeBinaryContent constructs a binary content string from text protobuf 203 // makeBinaryContent constructs a binary content string from text protobuf
205 // content. 204 // content.
206 // 205 //
207 // The binary content is formatted by concatenating two "cmpbin" binary values 206 // The binary content is formatted by concatenating two "cmpbin" binary values
208 // together: 207 // together:
209 // [Message Name] | [Marshaled Message Data] 208 // [Message Name] | [Marshaled Message Data]
210 func makeBinaryContent(msg proto.Message) (string, error) { 209 func makeBinaryContent(msg proto.Message) (string, error) {
211 d, err := proto.Marshal(msg) 210 d, err := proto.Marshal(msg)
212 if err != nil { 211 if err != nil {
213 » » return "", errors.Annotate(err).Reason("failed to marshal messag e").Err() 212 » » return "", errors.Annotate(err, "failed to marshal message").Err ()
214 } 213 }
215 214
216 var buf bytes.Buffer 215 var buf bytes.Buffer
217 if _, err := cmpbin.WriteString(&buf, proto.MessageName(msg)); err != ni l { 216 if _, err := cmpbin.WriteString(&buf, proto.MessageName(msg)); err != ni l {
218 » » return "", errors.Annotate(err).Reason("failed to write message name").Err() 217 » » return "", errors.Annotate(err, "failed to write message name"). Err()
219 } 218 }
220 if _, err := cmpbin.WriteBytes(&buf, d); err != nil { 219 if _, err := cmpbin.WriteBytes(&buf, d); err != nil {
221 » » return "", errors.Annotate(err).Reason("failed to write binary m essage content").Err() 220 » » return "", errors.Annotate(err, "failed to write binary message content").Err()
222 } 221 }
223 return buf.String(), nil 222 return buf.String(), nil
224 } 223 }
225 224
226 // parseBinaryContent parses a binary content string, pulling out the message 225 // parseBinaryContent parses a binary content string, pulling out the message
227 // type and marshalled message data. It then unmarshals the specified type into 226 // type and marshalled message data. It then unmarshals the specified type into
228 // a new message based on the archetype. 227 // a new message based on the archetype.
229 // 228 //
230 // If the binary content's declared type doesn't match the archetype, or if the 229 // If the binary content's declared type doesn't match the archetype, or if the
231 // binary content is invalid, an error will be returned. 230 // binary content is invalid, an error will be returned.
232 func parseBinaryContent(v string, msg proto.Message) error { 231 func parseBinaryContent(v string, msg proto.Message) error {
233 r := strings.NewReader(v) 232 r := strings.NewReader(v)
234 encName, _, err := cmpbin.ReadString(r) 233 encName, _, err := cmpbin.ReadString(r)
235 if err != nil { 234 if err != nil {
236 » » return errors.Annotate(err).Reason("failed to read message name" ).Err() 235 » » return errors.Annotate(err, "failed to read message name").Err()
237 } 236 }
238 237
239 // Construct a message for this. 238 // Construct a message for this.
240 if name := proto.MessageName(msg); name != encName { 239 if name := proto.MessageName(msg); name != encName {
241 » » return errors.Reason("message name %(name)q doesn't match encode d name %(enc)q"). 240 » » return errors.Reason("message name %q doesn't match encoded name %q", name, encName).Err()
242 » » » D("name", name).D("enc", encName).Err()
243 } 241 }
244 242
245 // We have the right message, unmarshal. 243 // We have the right message, unmarshal.
246 d, _, err := cmpbin.ReadBytes(r) 244 d, _, err := cmpbin.ReadBytes(r)
247 if err != nil { 245 if err != nil {
248 » » return errors.Annotate(err).Reason("failed to read binary messag e content").Err() 246 » » return errors.Annotate(err, "failed to read binary message conte nt").Err()
249 } 247 }
250 if err := proto.Unmarshal(d, msg); err != nil { 248 if err := proto.Unmarshal(d, msg); err != nil {
251 » » return errors.Annotate(err).Reason("failed to unmarshal message" ).Err() 249 » » return errors.Annotate(err, "failed to unmarshal message").Err()
252 } 250 }
253 return nil 251 return nil
254 } 252 }
OLDNEW
« no previous file with comments | « luci_config/server/cfgclient/resolver.go ('k') | lucictx/lucictx.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698