pomerium/pkg/protoutil/struct.go
Caleb Doxsey 1a5b8b606f
core/lint: upgrade golangci-lint, replace interface{} with any (#5099)
* core/lint: upgrade golangci-lint, replace interface{} with any

* regen proto
2024-05-02 14:33:52 -06:00

119 lines
2.9 KiB
Go

// 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},
}
}