192 // Parse populates p by parsing a string in the protobuf struct field tag style. |
191 // Parse populates p by parsing a string in the protobuf struct field tag style. |
193 func (p *Properties) Parse(s string) { |
192 func (p *Properties) Parse(s string) { |
194 // "bytes,49,opt,name=foo,def=hello!" |
193 // "bytes,49,opt,name=foo,def=hello!" |
195 fields := strings.Split(s, ",") // breaks def=, but handled below. |
194 fields := strings.Split(s, ",") // breaks def=, but handled below. |
196 if len(fields) < 2 { |
195 if len(fields) < 2 { |
197 fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) |
196 log.Printf("proto: tag has too few fields: %q", s) |
198 return |
197 return |
199 } |
198 } |
200 |
199 |
201 p.Wire = fields[0] |
200 p.Wire = fields[0] |
202 switch p.Wire { |
201 switch p.Wire { |
212 p.WireType = WireVarint |
211 p.WireType = WireVarint |
213 case "bytes", "group": |
212 case "bytes", "group": |
214 p.WireType = WireBytes |
213 p.WireType = WireBytes |
215 // no numeric converter for non-numeric types |
214 // no numeric converter for non-numeric types |
216 default: |
215 default: |
217 fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) |
216 log.Printf("proto: tag has unknown wire type: %q", s) |
218 return |
217 return |
219 } |
218 } |
220 |
219 |
221 var err error |
220 var err error |
222 p.Tag, err = strconv.Atoi(fields[1]) |
221 p.Tag, err = strconv.Atoi(fields[1]) |
332 // retrieving details for types we have seen before. |
331 // retrieving details for types we have seen before. |
333 propertiesMu.RLock() |
332 propertiesMu.RLock() |
334 sprop, ok := propertiesMap[t] |
333 sprop, ok := propertiesMap[t] |
335 propertiesMu.RUnlock() |
334 propertiesMu.RUnlock() |
336 if ok { |
335 if ok { |
337 if collectStats { |
|
338 stats.Chit++ |
|
339 } |
|
340 return sprop |
336 return sprop |
341 } |
337 } |
342 |
338 |
343 propertiesMu.Lock() |
339 propertiesMu.Lock() |
344 sprop = getPropertiesLocked(t) |
340 sprop = getPropertiesLocked(t) |
345 propertiesMu.Unlock() |
341 propertiesMu.Unlock() |
346 return sprop |
342 return sprop |
347 } |
343 } |
348 |
344 |
|
345 type ( |
|
346 oneofFuncsIface interface { |
|
347 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) |
|
348 } |
|
349 oneofWrappersIface interface { |
|
350 XXX_OneofWrappers() []interface{} |
|
351 } |
|
352 ) |
|
353 |
349 // getPropertiesLocked requires that propertiesMu is held. |
354 // getPropertiesLocked requires that propertiesMu is held. |
350 func getPropertiesLocked(t reflect.Type) *StructProperties { |
355 func getPropertiesLocked(t reflect.Type) *StructProperties { |
351 if prop, ok := propertiesMap[t]; ok { |
356 if prop, ok := propertiesMap[t]; ok { |
352 if collectStats { |
|
353 stats.Chit++ |
|
354 } |
|
355 return prop |
357 return prop |
356 } |
|
357 if collectStats { |
|
358 stats.Cmiss++ |
|
359 } |
358 } |
360 |
359 |
361 prop := new(StructProperties) |
360 prop := new(StructProperties) |
362 // in case of recursive protos, fill this in now. |
361 // in case of recursive protos, fill this in now. |
363 propertiesMap[t] = prop |
362 propertiesMap[t] = prop |
389 } |
388 } |
390 |
389 |
391 // Re-order prop.order. |
390 // Re-order prop.order. |
392 sort.Sort(prop) |
391 sort.Sort(prop) |
393 |
392 |
394 type oneofMessage interface { |
393 var oots []interface{} |
395 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) |
394 switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { |
396 } |
395 case oneofFuncsIface: |
397 if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { |
396 _, _, _, oots = m.XXX_OneofFuncs() |
398 var oots []interface{} |
397 case oneofWrappersIface: |
399 _, _, _, oots = om.XXX_OneofFuncs() |
398 oots = m.XXX_OneofWrappers() |
400 |
399 } |
|
400 if len(oots) > 0 { |
401 // Interpret oneof metadata. |
401 // Interpret oneof metadata. |
402 prop.OneofTypes = make(map[string]*OneofProperties) |
402 prop.OneofTypes = make(map[string]*OneofProperties) |
403 for _, oot := range oots { |
403 for _, oot := range oots { |
404 oop := &OneofProperties{ |
404 oop := &OneofProperties{ |
405 Type: reflect.ValueOf(oot).Type(), // *T |
405 Type: reflect.ValueOf(oot).Type(), // *T |