1 package ldstoreimpl 2 3 import ( 4 "github.com/launchdarkly/go-sdk-common/v3/ldvalue" 5 "github.com/launchdarkly/go-server-sdk/v6/subsystems" 6 ) 7 8 // NewBigSegmentMembershipFromSegmentRefs creates a BigSegmentMembership based on the specified 9 // lists of included and excluded segment references. This method is intended to be used by Big 10 // Segment store implementations; application code does not need to use it. 11 // 12 // As described in interfaces.BigSegmentMembership, a segmentRef is not the same as the key 13 // property in the segment data model; it includes the key but also versioning information that the 14 // SDK will provide. The store implementation should not be concerned with the format of this. 15 // 16 // The returned object's CheckMembership method will return ldvalue.NewOptionalBool(true) for any 17 // segmentRef that is in the included list, ldvalue.NewOptionalBool(false) for any segmentRef that 18 // is in the excluded list and *not* also in the included list, and ldvalue.OptionalBool{} 19 // (undefined) for all others. 20 // 21 // The exact implementation type of the returned value may vary, to provide the most efficient 22 // representation of the data. 23 func NewBigSegmentMembershipFromSegmentRefs( 24 includedSegmentRefs []string, 25 excludedSegmentRefs []string, 26 ) subsystems.BigSegmentMembership { 27 if len(includedSegmentRefs) == 0 && len(excludedSegmentRefs) == 0 { 28 return bigSegmentMembershipMapImpl(nil) 29 } 30 if len(includedSegmentRefs) == 1 && len(excludedSegmentRefs) == 0 { 31 return bigSegmentMembershipSingleInclude(includedSegmentRefs[0]) 32 } 33 if len(includedSegmentRefs) == 0 && len(excludedSegmentRefs) == 1 { 34 return bigSegmentMembershipSingleExclude(excludedSegmentRefs[0]) 35 } 36 ret := make(bigSegmentMembershipMapImpl, len(includedSegmentRefs)+len(excludedSegmentRefs)) 37 for _, exc := range excludedSegmentRefs { 38 ret[exc] = false 39 } 40 for _, inc := range includedSegmentRefs { // includes override excludes 41 ret[inc] = true 42 } 43 return ret 44 } 45 46 // This is the standard internal implementation of BigSegmentMembership. The map contains a true 47 // value for included keys and a false value for excluded keys that are not also included (inclusions 48 // override exclusions). If there are no keys at all, we store nil instead of allocating an empty map. 49 // 50 // Using a type that is simply a rename of a map is an efficient way to implement an interface, because 51 // no additional data structure besides the map needs to be allocated on the heap; the interface value 52 // contains only the type identifier and the map reference. 53 type bigSegmentMembershipMapImpl map[string]bool 54 55 // This is an alternate implementation of BigSegmentMembership used when there is only one key 56 // in the included list, and no keys in the excluded list, so there's no need to allocate a map. 57 type bigSegmentMembershipSingleInclude string 58 59 // This is an alternate implementation of BigSegmentMembership used when there is only one key 60 // in the excluded list, and no keys in the included list, so there's no need to allocate a map. 61 type bigSegmentMembershipSingleExclude string 62 63 func (u bigSegmentMembershipMapImpl) CheckMembership(segmentRef string) ldvalue.OptionalBool { 64 value, found := u[segmentRef] 65 if found { 66 return ldvalue.NewOptionalBool(value) 67 } 68 return ldvalue.OptionalBool{} 69 } 70 71 func (u bigSegmentMembershipSingleInclude) CheckMembership(segmentRef string) ldvalue.OptionalBool { 72 if segmentRef == string(u) { 73 return ldvalue.NewOptionalBool(true) 74 } 75 return ldvalue.OptionalBool{} 76 } 77 78 func (u bigSegmentMembershipSingleExclude) CheckMembership(segmentRef string) ldvalue.OptionalBool { 79 if segmentRef == string(u) { 80 return ldvalue.NewOptionalBool(false) 81 } 82 return ldvalue.OptionalBool{} 83 } 84