360 // Store the info in the correct slot in the message. |
360 // Store the info in the correct slot in the message. |
361 u.setTag(tag, toField(&f), unmarshal, reqMask, name) |
361 u.setTag(tag, toField(&f), unmarshal, reqMask, name) |
362 } |
362 } |
363 |
363 |
364 // Find any types associated with oneof fields. |
364 // Find any types associated with oneof fields. |
365 // TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? |
365 var oneofImplementers []interface{} |
366 fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") |
366 switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { |
367 if fn.IsValid() { |
367 case oneofFuncsIface: |
368 res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} |
368 _, _, _, oneofImplementers = m.XXX_OneofFuncs() |
369 for i := res.Len() - 1; i >= 0; i-- { |
369 case oneofWrappersIface: |
370 v := res.Index(i) // interface{} |
370 oneofImplementers = m.XXX_OneofWrappers() |
371 tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X |
371 } |
372 typ := tptr.Elem() // Msg_X |
372 for _, v := range oneofImplementers { |
373 |
373 tptr := reflect.TypeOf(v) // *Msg_X |
374 f := typ.Field(0) // oneof implementers have one field |
374 typ := tptr.Elem() // Msg_X |
375 baseUnmarshal := fieldUnmarshaler(&f) |
375 |
376 tags := strings.Split(f.Tag.Get("protobuf"), ",") |
376 f := typ.Field(0) // oneof implementers have one field |
377 fieldNum, err := strconv.Atoi(tags[1]) |
377 baseUnmarshal := fieldUnmarshaler(&f) |
378 if err != nil { |
378 tags := strings.Split(f.Tag.Get("protobuf"), ",") |
379 panic("protobuf tag field not an integer: " + tags[1]) |
379 fieldNum, err := strconv.Atoi(tags[1]) |
380 } |
380 if err != nil { |
381 var name string |
381 panic("protobuf tag field not an integer: " + tags[1]) |
382 for _, tag := range tags { |
382 } |
383 if strings.HasPrefix(tag, "name=") { |
383 var name string |
384 name = strings.TrimPrefix(tag, "name=") |
384 for _, tag := range tags { |
385 break |
385 if strings.HasPrefix(tag, "name=") { |
386 } |
386 name = strings.TrimPrefix(tag, "name=") |
387 } |
387 break |
388 |
388 } |
389 // Find the oneof field that this struct implements. |
389 } |
390 // Might take O(n^2) to process all of the oneofs, but who cares. |
390 |
391 for _, of := range oneofFields { |
391 // Find the oneof field that this struct implements. |
392 if tptr.Implements(of.ityp) { |
392 // Might take O(n^2) to process all of the oneofs, but who cares. |
393 // We have found the corresponding interface for this struct. |
393 for _, of := range oneofFields { |
394 // That lets us know where this struct should be stored |
394 if tptr.Implements(of.ityp) { |
395 // when we encounter it during unmarshaling. |
395 // We have found the corresponding interface for this struct. |
396 unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) |
396 // That lets us know where this struct should be stored |
397 u.setTag(fieldNum, of.field, unmarshal, 0, name) |
397 // when we encounter it during unmarshaling. |
398 } |
398 unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) |
399 } |
399 u.setTag(fieldNum, of.field, unmarshal, 0, name) |
400 } |
400 } |
|
401 } |
|
402 |
401 } |
403 } |
402 |
404 |
403 // Get extension ranges, if any. |
405 // Get extension ranges, if any. |
404 fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") |
406 fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") |
405 if fn.IsValid() { |
407 if fn.IsValid() { |
406 if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { |
408 if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { |
407 panic("a message with extensions, but no extensions field in " + t.Name()) |
409 panic("a message with extensions, but no extensions field in " + t.Name()) |
408 } |
410 } |
409 u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) |
411 u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange) |