| 330 | } |
| 331 | |
| 332 | func fieldInfoForMessage(fd protoreflect.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { |
| 333 | ft := fs.Type |
| 334 | conv := NewConverter(ft, fd) |
| 335 | |
| 336 | // TODO: Implement unsafe fast path? |
| 337 | fieldOffset := offsetOf(fs) |
| 338 | return fieldInfo{ |
| 339 | fieldDesc: fd, |
| 340 | has: func(p pointer) bool { |
| 341 | if p.IsNil() { |
| 342 | return false |
| 343 | } |
| 344 | rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() |
| 345 | if fs.Type.Kind() != reflect.Ptr { |
| 346 | return !rv.IsZero() |
| 347 | } |
| 348 | return !rv.IsNil() |
| 349 | }, |
| 350 | clear: func(p pointer) { |
| 351 | rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() |
| 352 | rv.Set(reflect.Zero(rv.Type())) |
| 353 | }, |
| 354 | get: func(p pointer) protoreflect.Value { |
| 355 | if p.IsNil() { |
| 356 | return conv.Zero() |
| 357 | } |
| 358 | rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() |
| 359 | return conv.PBValueOf(rv) |
| 360 | }, |
| 361 | set: func(p pointer, v protoreflect.Value) { |
| 362 | rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() |
| 363 | rv.Set(conv.GoValueOf(v)) |
| 364 | if fs.Type.Kind() == reflect.Ptr && rv.IsNil() { |
| 365 | panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName())) |
| 366 | } |
| 367 | }, |
| 368 | mutable: func(p pointer) protoreflect.Value { |
| 369 | rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() |
| 370 | if fs.Type.Kind() == reflect.Ptr && rv.IsNil() { |
| 371 | rv.Set(conv.GoValueOf(conv.New())) |
| 372 | } |
| 373 | return conv.PBValueOf(rv) |
| 374 | }, |
| 375 | newMessage: func() protoreflect.Message { |
| 376 | return conv.New().Message() |
| 377 | }, |
| 378 | newField: func() protoreflect.Value { |
| 379 | return conv.New() |
| 380 | }, |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | type oneofInfo struct { |
| 385 | oneofDesc protoreflect.OneofDescriptor |