@@ -48,12 +48,44 @@ func EncodeValue(val interface{}, t enumspb.IndexedValueType) (*commonpb.Payload
48
48
// DecodeValue decodes search attribute value from Payload using (in order):
49
49
// 1. passed type t.
50
50
// 2. type from MetadataType field, if t is not specified.
51
- func DecodeValue (value * commonpb.Payload , t enumspb.IndexedValueType ) (interface {}, error ) {
51
+ // allowList allows list of values when it's not keyword list type.
52
+ func DecodeValue (
53
+ value * commonpb.Payload ,
54
+ t enumspb.IndexedValueType ,
55
+ allowList bool ,
56
+ ) (any , error ) {
52
57
if t == enumspb .INDEXED_VALUE_TYPE_UNSPECIFIED {
53
- t = enumspb .IndexedValueType (enumspb .IndexedValueType_value [string (value .Metadata [MetadataType ])])
58
+ t = enumspb .IndexedValueType (
59
+ enumspb .IndexedValueType_value [string (value .Metadata [MetadataType ])],
60
+ )
54
61
}
55
62
56
- // Here are similar code sections for all types.
63
+ switch t {
64
+ case enumspb .INDEXED_VALUE_TYPE_BOOL :
65
+ return decodeValueTyped [bool ](value , allowList )
66
+ case enumspb .INDEXED_VALUE_TYPE_DATETIME :
67
+ return decodeValueTyped [time.Time ](value , allowList )
68
+ case enumspb .INDEXED_VALUE_TYPE_DOUBLE :
69
+ return decodeValueTyped [float64 ](value , allowList )
70
+ case enumspb .INDEXED_VALUE_TYPE_INT :
71
+ return decodeValueTyped [int64 ](value , allowList )
72
+ case enumspb .INDEXED_VALUE_TYPE_KEYWORD :
73
+ return decodeValueTyped [string ](value , allowList )
74
+ case enumspb .INDEXED_VALUE_TYPE_TEXT :
75
+ return decodeValueTyped [string ](value , allowList )
76
+ case enumspb .INDEXED_VALUE_TYPE_KEYWORD_LIST :
77
+ return decodeValueTyped [[]string ](value , false )
78
+ default :
79
+ return nil , fmt .Errorf ("%w: %v" , ErrInvalidType , t )
80
+ }
81
+ }
82
+
83
+ // decodeValueTyped tries to decode to the given type.
84
+ // If the input is a list and allowList is false, then it will return only the first element.
85
+ // If the input is a list and allowList is true, then it will return the decoded list.
86
+ //
87
+ //nolint:revive // allowList is a control flag
88
+ func decodeValueTyped [T any ](value * commonpb.Payload , allowList bool ) (any , error ) {
57
89
// At first, it tries to decode to pointer of actual type (i.e. `*string` for `string`).
58
90
// This is to ensure that `nil` values are decoded back as `nil` using `NilPayloadConverter`.
59
91
// If value is not `nil` but some value of expected type, the code relies on the fact that
@@ -62,82 +94,28 @@ func DecodeValue(value *commonpb.Payload, t enumspb.IndexedValueType) (interface
62
94
// If decoding to pointer type fails, it tries to decode to array of the same type because
63
95
// search attributes support polymorphism: field of specific type may also have an array of that type.
64
96
// If resulting slice has zero length, it gets substitute with `nil` to treat nils and empty slices equally.
97
+ // If allowList is true, it returns the list as it is. If allowList is false and the list has
98
+ // only one element, then return it. Otherwise, return an error.
65
99
// If search attribute value is `nil`, it means that search attribute needs to be removed from the document.
66
-
67
- switch t {
68
- case enumspb .INDEXED_VALUE_TYPE_TEXT ,
69
- enumspb .INDEXED_VALUE_TYPE_KEYWORD ,
70
- enumspb .INDEXED_VALUE_TYPE_KEYWORD_LIST :
71
- var val * string
72
- if err := payload .Decode (value , & val ); err != nil {
73
- var listVal []string
74
- err = payload .Decode (value , & listVal )
75
- if len (listVal ) == 0 {
76
- return nil , err
77
- }
78
- return listVal , err
79
- }
80
- if val == nil {
81
- return nil , nil
100
+ var val * T
101
+ if err := payload .Decode (value , & val ); err != nil {
102
+ var listVal []T
103
+ if err := payload .Decode (value , & listVal ); err != nil {
104
+ return nil , err
82
105
}
83
- return * val , nil
84
- case enumspb .INDEXED_VALUE_TYPE_INT :
85
- var val * int64
86
- if err := payload .Decode (value , & val ); err != nil {
87
- var listVal []int64
88
- err = payload .Decode (value , & listVal )
89
- if len (listVal ) == 0 {
90
- return nil , err
91
- }
92
- return listVal , err
93
- }
94
- if val == nil {
95
- return nil , nil
96
- }
97
- return * val , nil
98
- case enumspb .INDEXED_VALUE_TYPE_DOUBLE :
99
- var val * float64
100
- if err := payload .Decode (value , & val ); err != nil {
101
- var listVal []float64
102
- err = payload .Decode (value , & listVal )
103
- if len (listVal ) == 0 {
104
- return nil , err
105
- }
106
- return listVal , err
107
- }
108
- if val == nil {
106
+ if len (listVal ) == 0 {
109
107
return nil , nil
110
108
}
111
- return * val , nil
112
- case enumspb .INDEXED_VALUE_TYPE_BOOL :
113
- var val * bool
114
- if err := payload .Decode (value , & val ); err != nil {
115
- var listVal []bool
116
- err = payload .Decode (value , & listVal )
117
- if len (listVal ) == 0 {
118
- return nil , err
119
- }
120
- return listVal , err
109
+ if allowList {
110
+ return listVal , nil
121
111
}
122
- if val == nil {
123
- return nil , nil
112
+ if len ( listVal ) == 1 {
113
+ return listVal [ 0 ] , nil
124
114
}
125
- return * val , nil
126
- case enumspb .INDEXED_VALUE_TYPE_DATETIME :
127
- var val * time.Time
128
- if err := payload .Decode (value , & val ); err != nil {
129
- var listVal []time.Time
130
- err = payload .Decode (value , & listVal )
131
- if len (listVal ) == 0 {
132
- return nil , err
133
- }
134
- return listVal , err
135
- }
136
- if val == nil {
137
- return nil , nil
138
- }
139
- return * val , nil
140
- default :
141
- return nil , fmt .Errorf ("%w: %v" , ErrInvalidType , t )
115
+ return nil , fmt .Errorf ("list of values not allowed for type %T" , listVal [0 ])
116
+ }
117
+ if val == nil {
118
+ return nil , nil
142
119
}
120
+ return * val , nil
143
121
}
0 commit comments