models/v3/msgs/subject.go (36 lines of code) (raw):

package msgs import ( "slices" "github.com/Azure/arn-sdk/models/v3/schema/types" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" ) // arm.ResourceID is implemented a singly linked list. The head of the list represents the entire resource ID. If rid.Parent is not nil, // it points to an arm.ResourceID representing the next valid parent scope. The tail of the list is always a shared root arm.ResourceID // representing the tenant. // // As the linked list is only singly linked and we will want to walk it in reverse, we work with pre-prepared slices containing pointers to // each of the nodes ([]*arm.ResourceID). // asSlice returns a slice containing pointers to each of the nodes of rid. func asSlice(rid *arm.ResourceID) (rids []*arm.ResourceID) { for ; rid != nil; rid = rid.Parent { rids = append(rids, rid) } return rids } // subject returns in string form the maximal arm.ResourceID which is a shared prefix of all of the resources in res. At least one // *types.NotificationResource must be passed to this function. func subject(res []types.NotificationResource) string { if len(res) == 0 { return "" } max := asSlice(res[0].ArmResource.ResourceID()) for i := 1; i < len(res); i++ { max = maxSharedPrefix(max, asSlice(res[i].ArmResource.ResourceID())) } if len(max) <= 1 { // only the tenant-level scope was shared or no scopes were shared return "/" } return max[0].String() } // maxSharedPrefix returns in slice form the maximal arm.ResourceID which is a shared prefix of a and b. func maxSharedPrefix(a, b []*arm.ResourceID) (results []*arm.ResourceID) { // We can find the maximal arm.ResourceID which is a shared prefix of a and b by walking the slices backwards comparing their scopes. // While the scopes match, we append the scope to results. By definition, a[len(a)-1] and b[len(b)-1] match. Note that a and b may // have a significant shared prefix without having the same length. for i := 1; len(a)-i >= 0 && len(b)-i >= 0; i++ { // We compare using String() because unfortunately isChild is unexported. At least String() caches its result internally. if a[len(a)-i].String() == b[len(b)-i].String() { results = append(results, a[len(a)-i]) } else { break } } slices.Reverse(results) return results }