@@ -3,6 +3,7 @@ package chasm
33import (
44 "errors"
55 "fmt"
6+ "reflect"
67 "time"
78
89 enumspb "go.temporal.io/api/enums/v1"
@@ -67,13 +68,19 @@ var (
6768)
6869
6970var (
70- _ SearchAttribute = (* searchAttributeDefinition )(nil )
7171 _ SearchAttribute = (* SearchAttributeBool )(nil )
7272 _ SearchAttribute = (* SearchAttributeDateTime )(nil )
7373 _ SearchAttribute = (* SearchAttributeInt )(nil )
7474 _ SearchAttribute = (* SearchAttributeDouble )(nil )
7575 _ SearchAttribute = (* SearchAttributeKeyword )(nil )
7676 _ SearchAttribute = (* SearchAttributeKeywordList )(nil )
77+
78+ _ typedSearchAttribute [bool ] = (* SearchAttributeBool )(nil )
79+ _ typedSearchAttribute [time.Time ] = (* SearchAttributeDateTime )(nil )
80+ _ typedSearchAttribute [int64 ] = (* SearchAttributeInt )(nil )
81+ _ typedSearchAttribute [float64 ] = (* SearchAttributeDouble )(nil )
82+ _ typedSearchAttribute [string ] = (* SearchAttributeKeyword )(nil )
83+ _ typedSearchAttribute [[]string ] = (* SearchAttributeKeywordList )(nil )
7784)
7885
7986type (
@@ -82,6 +89,12 @@ type (
8289 definition () searchAttributeDefinition
8390 }
8491
92+ typedSearchAttribute [T any ] interface {
93+ SearchAttribute
94+ typeMarker (T )
95+ markedVisibilityType () reflect.Type
96+ }
97+
8598 searchAttributeDefinition struct {
8699 alias string
87100 field string
@@ -210,6 +223,12 @@ func (s SearchAttributeBool) Value(value bool) SearchAttributeKeyValue {
210223 }
211224}
212225
226+ func (s SearchAttributeBool ) typeMarker (_ bool ) {}
227+
228+ func (s SearchAttributeBool ) markedVisibilityType () reflect.Type {
229+ return reflect .TypeFor [VisibilityValueBool ]()
230+ }
231+
213232// SearchAttributeDateTime is a search attribute for a datetime value.
214233type SearchAttributeDateTime struct {
215234 searchAttributeDefinition
@@ -245,6 +264,12 @@ func (s SearchAttributeDateTime) Value(value time.Time) SearchAttributeKeyValue
245264 }
246265}
247266
267+ func (s SearchAttributeDateTime ) typeMarker (_ time.Time ) {}
268+
269+ func (s SearchAttributeDateTime ) markedVisibilityType () reflect.Type {
270+ return reflect .TypeFor [VisibilityValueTime ]()
271+ }
272+
248273// SearchAttributeInt is a search attribute for an integer value.
249274type SearchAttributeInt struct {
250275 searchAttributeDefinition
@@ -280,6 +305,12 @@ func (s SearchAttributeInt) Value(value int64) SearchAttributeKeyValue {
280305 }
281306}
282307
308+ func (s SearchAttributeInt ) typeMarker (_ int64 ) {}
309+
310+ func (s SearchAttributeInt ) markedVisibilityType () reflect.Type {
311+ return reflect .TypeFor [VisibilityValueInt64 ]()
312+ }
313+
283314// SearchAttributeDouble is a search attribute for a double value.
284315type SearchAttributeDouble struct {
285316 searchAttributeDefinition
@@ -315,6 +346,12 @@ func (s SearchAttributeDouble) Value(value float64) SearchAttributeKeyValue {
315346 }
316347}
317348
349+ func (s SearchAttributeDouble ) typeMarker (_ float64 ) {}
350+
351+ func (s SearchAttributeDouble ) markedVisibilityType () reflect.Type {
352+ return reflect .TypeFor [VisibilityValueFloat64 ]()
353+ }
354+
318355// SearchAttributeKeyword is a search attribute for a keyword value.
319356type SearchAttributeKeyword struct {
320357 searchAttributeDefinition
@@ -350,6 +387,12 @@ func (s SearchAttributeKeyword) Value(value string) SearchAttributeKeyValue {
350387 }
351388}
352389
390+ func (s SearchAttributeKeyword ) typeMarker (_ string ) {}
391+
392+ func (s SearchAttributeKeyword ) markedVisibilityType () reflect.Type {
393+ return reflect .TypeFor [VisibilityValueString ]()
394+ }
395+
353396// SearchAttributeKeywordList is a search attribute for a keyword list value.
354397type SearchAttributeKeywordList struct {
355398 searchAttributeDefinition
@@ -385,6 +428,12 @@ func (s SearchAttributeKeywordList) Value(value []string) SearchAttributeKeyValu
385428 }
386429}
387430
431+ func (s SearchAttributeKeywordList ) typeMarker (_ []string ) {}
432+
433+ func (s SearchAttributeKeywordList ) markedVisibilityType () reflect.Type {
434+ return reflect .TypeFor [VisibilityValueStringSlice ]()
435+ }
436+
388437// SearchAttributesMap wraps search attribute values with type-safe access.
389438type SearchAttributesMap struct {
390439 values map [string ]VisibilityValue
@@ -395,94 +444,39 @@ func NewSearchAttributesMap(values map[string]VisibilityValue) SearchAttributesM
395444 return SearchAttributesMap {values : values }
396445}
397446
398- // GetBool returns the boolean value for a given SearchAttributeBool. If not found or map is nil, found is false.
399- func (m SearchAttributesMap ) GetBool (sa SearchAttributeBool ) (value bool , found bool ) {
447+ // Get returns the value for a given SearchAttribute with compile-time type safety.
448+ // The return type T is inferred from the SearchAttribute's type parameter.
449+ // For example, SearchAttriteBool will return a bool value.
450+ // If the value is not found, the zero value for the type T is returned and the second return value is false.
451+ func Get [T any ](m SearchAttributesMap , sa typedSearchAttribute [T ]) (val T , ok bool ) {
452+ var zero T
400453 if m .values == nil {
401- return false , false
454+ return zero , false
402455 }
403456
404457 alias := sa .definition ().alias
405- boolVal , ok := m .values [alias ].( VisibilityValueBool )
406- if ! ok {
407- return false , false
458+ visibilityValue , exists := m .values [alias ]
459+ if ! exists {
460+ return zero , false
408461 }
409462
410- return bool (boolVal ), true
411- }
412-
413- // GetInt returns the int value for a given SearchAttributeInt. If not found or map is nil, second parameter is false.
414- func (m SearchAttributesMap ) GetInt (sa SearchAttributeInt ) (int , bool ) {
415- if m .values == nil {
416- return 0 , false
463+ if reflect .TypeOf (visibilityValue ) != sa .markedVisibilityType () {
464+ return zero , false
417465 }
418466
419- alias := sa .definition ().alias
420- intValue , ok := m .values [alias ].(VisibilityValueInt )
421- if ! ok {
422- return 0 , false
423- }
424-
425- return int (intValue ), true
426- }
467+ reflectVal := reflect .ValueOf (val )
468+ targetType := reflect .TypeFor [T ]()
427469
428- // GetDouble returns the double value for a given SearchAttributeDouble. If not found or map is nil, second parameter is false.
429- func (m SearchAttributesMap ) GetDouble (sa SearchAttributeDouble ) (float64 , bool ) {
430- if m .values == nil {
431- return 0 , false
432- }
433-
434- alias := sa .definition ().alias
435- doubleValue , ok := m .values [alias ].(VisibilityValueFloat64 )
436- if ! ok {
437- return 0 , false
470+ if ! reflectVal .Type ().ConvertibleTo (targetType ) {
471+ return zero , false
438472 }
439473
440- return float64 (doubleValue ), true
441- }
442-
443- // GetKeyword returns the string value for a given SearchAttributeKeyword. If not found or map is nil, second parameter is false.
444- func (m SearchAttributesMap ) GetKeyword (sa SearchAttributeKeyword ) (string , bool ) {
445- if m .values == nil {
446- return "" , false
447- }
448-
449- alias := sa .definition ().alias
450- stringValue , ok := m .values [alias ].(VisibilityValueString )
451- if ! ok {
452- return "" , false
453- }
454-
455- return string (stringValue ), true
456- }
457-
458- // GetDateTime returns the time value for a given SearchAttributeDateTime. If not found or map is nil, second parameter is false.
459- func (m SearchAttributesMap ) GetDateTime (sa SearchAttributeDateTime ) (time.Time , bool ) {
460- if m .values == nil {
461- return time.Time {}, false
462- }
463-
464- alias := sa .definition ().alias
465- timeValue , ok := m .values [alias ].(VisibilityValueTime )
466- if ! ok {
467- return time.Time {}, false
468- }
469-
470- return time .Time (timeValue ), true
471- }
472-
473- // GetKeywordList returns the string list value for a given SearchAttributeKeywordList. If not found or map is nil, second parameter is false.
474- func (m SearchAttributesMap ) GetKeywordList (sa SearchAttributeKeywordList ) ([]string , bool ) {
475- if m .values == nil {
476- return nil , false
477- }
478-
479- alias := sa .definition ().alias
480- keywordListValue , ok := m .values [alias ].(VisibilityValueStringSlice )
474+ result , ok := reflectVal .Convert (targetType ).Interface ().(T )
481475 if ! ok {
482- return nil , false
476+ return zero , false
483477 }
484478
485- return [] string ( keywordListValue ) , true
479+ return result , true
486480}
487481
488482// convertToVisibilityValue converts a value to VisibilityValue based on its runtime type.
0 commit comments