ProtoToStruct uses reflection to convert a proto to a Mangle struct. The resulting struct only contains that are considered populated by the go protobuf runtime, i.e. proto fields set to default values will be missing.
(msg protoreflect.Message)
| 26 | // The resulting struct only contains that are considered populated by the |
| 27 | // go protobuf runtime, i.e. proto fields set to default values will be missing. |
| 28 | func ProtoToStruct(msg protoreflect.Message) (ast.Constant, error) { |
| 29 | structEntries := map[*ast.Constant]*ast.Constant{} |
| 30 | var err error |
| 31 | msg.Range(func(fd protoreflect.FieldDescriptor, val protoreflect.Value) bool { |
| 32 | fieldName, errLocal := ast.Name("/" + fd.TextName()) |
| 33 | if errLocal != nil { |
| 34 | err = fmt.Errorf("Could not convert field name %v: %v", fieldName, errLocal) |
| 35 | return false |
| 36 | } |
| 37 | if fd.IsMap() { |
| 38 | entries := map[*ast.Constant]*ast.Constant{} |
| 39 | // We cannot use ast.MapCons here since the runtime representation assumes a |
| 40 | // particular order of the entries. So we collect all entries first. |
| 41 | val.Map().Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { |
| 42 | key, errLocal := ProtoValueToConstant(fd.MapKey(), k.Value()) |
| 43 | if errLocal != nil { |
| 44 | err = fmt.Errorf("Could not convert map key %v: %v", k, errLocal) |
| 45 | return false |
| 46 | } |
| 47 | value, errLocal := ProtoValueToConstant(fd.MapValue(), v) |
| 48 | if errLocal != nil { |
| 49 | err = fmt.Errorf("Could not convert message field %v: %v", fd.TextName(), errLocal) |
| 50 | return false |
| 51 | } |
| 52 | entries[&key] = &value |
| 53 | return true |
| 54 | }) |
| 55 | if err != nil { |
| 56 | err = fmt.Errorf("Could not convert map %v: %v", val, err) |
| 57 | return false |
| 58 | } |
| 59 | structEntries[&fieldName] = ast.Map(entries) |
| 60 | return true |
| 61 | } |
| 62 | |
| 63 | if fd.IsList() { |
| 64 | l := &ast.ListNil |
| 65 | for i := val.List().Len() - 1; 0 <= i; i-- { |
| 66 | value, errLocal := ProtoValueToConstant(fd, val.List().Get(i)) |
| 67 | if errLocal != nil { |
| 68 | err = errLocal |
| 69 | return false |
| 70 | } |
| 71 | elem := ast.ListCons(&value, l) |
| 72 | l = &elem |
| 73 | } |
| 74 | structEntries[&fieldName] = l |
| 75 | return true |
| 76 | } |
| 77 | value, errLocal := ProtoValueToConstant(fd, val) |
| 78 | if errLocal != nil { |
| 79 | err = errLocal |
| 80 | return false |
| 81 | } |
| 82 | structEntries[&fieldName] = &value |
| 83 | return true |
| 84 | }) |
| 85 | if err != nil { |
no test coverage detected