-
Notifications
You must be signed in to change notification settings - Fork 280
/
struct.go
119 lines (106 loc) · 2.88 KB
/
struct.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Package protoutil contains functions for working with protobuf types.
package protoutil
import (
"fmt"
"reflect"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
)
// ToStruct converts any value into a structpb Value.
func ToStruct(value any) *structpb.Value {
if value == nil {
return NewStructNull()
}
switch v := value.(type) {
case bool:
return NewStructBool(v)
case float64:
return NewStructNumber(v)
case float32:
return NewStructNumber(float64(v))
case int:
return NewStructNumber(float64(v))
case int8:
return NewStructNumber(float64(v))
case int16:
return NewStructNumber(float64(v))
case int32:
return NewStructNumber(float64(v))
case int64:
return NewStructNumber(float64(v))
case string:
return NewStructString(v)
case uint:
return NewStructNumber(float64(v))
case uint8:
return NewStructNumber(float64(v))
case uint16:
return NewStructNumber(float64(v))
case uint32:
return NewStructNumber(float64(v))
case uint64:
return NewStructNumber(float64(v))
}
if msg, ok := value.(proto.Message); ok {
bs, _ := protojson.Marshal(msg)
var s structpb.Struct
_ = protojson.Unmarshal(bs, &s)
return &structpb.Value{
Kind: &structpb.Value_StructValue{StructValue: &s},
}
}
rv := reflect.ValueOf(value)
switch rv.Kind() {
case reflect.Slice:
svs := make([]*structpb.Value, rv.Len())
for i := range svs {
svs[i] = ToStruct(rv.Index(i).Interface())
}
return NewStructList(svs...)
case reflect.Map:
svm := make(map[string]*structpb.Value)
iter := rv.MapRange()
for iter.Next() {
svm[fmt.Sprint(iter.Key().Interface())] = ToStruct(iter.Value().Interface())
}
return NewStructMap(svm)
}
return NewStructNull()
}
// NewStructBool creates a new bool struct value.
func NewStructBool(v bool) *structpb.Value {
return &structpb.Value{
Kind: &structpb.Value_BoolValue{BoolValue: v},
}
}
// NewStructMap creates a new map struct value.
func NewStructMap(v map[string]*structpb.Value) *structpb.Value {
return &structpb.Value{
Kind: &structpb.Value_StructValue{StructValue: &structpb.Struct{Fields: v}},
}
}
// NewStructNull creates a new null struct value.
func NewStructNull() *structpb.Value {
return &structpb.Value{
Kind: &structpb.Value_NullValue{},
}
}
// NewStructNumber creates a new number struct value.
func NewStructNumber(v float64) *structpb.Value {
return &structpb.Value{
Kind: &structpb.Value_NumberValue{NumberValue: v},
}
}
// NewStructList creates a new list struct value.
func NewStructList(vs ...*structpb.Value) *structpb.Value {
return &structpb.Value{
Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{Values: vs}},
}
}
// NewStructString creates a new string struct value.
func NewStructString(v string) *structpb.Value {
return &structpb.Value{
Kind: &structpb.Value_StringValue{StringValue: v},
}
}