arn.go (2113B)
1 package awsrulesfn 2 3 import ( 4 "strings" 5 ) 6 7 // ARN provides AWS ARN components broken out into a data structure. 8 type ARN struct { 9 Partition string 10 Service string 11 Region string 12 AccountId string 13 ResourceId OptionalStringSlice 14 } 15 16 const ( 17 arnDelimiters = ":" 18 resourceDelimiters = "/:" 19 arnSections = 6 20 arnPrefix = "arn:" 21 22 // zero-indexed 23 sectionPartition = 1 24 sectionService = 2 25 sectionRegion = 3 26 sectionAccountID = 4 27 sectionResource = 5 28 ) 29 30 // ParseARN returns an [ARN] value parsed from the input string provided. If 31 // the ARN cannot be parsed nil will be returned, and error added to 32 // [ErrorCollector]. 33 func ParseARN(input string) *ARN { 34 if !strings.HasPrefix(input, arnPrefix) { 35 return nil 36 } 37 38 sections := strings.SplitN(input, arnDelimiters, arnSections) 39 if numSections := len(sections); numSections != arnSections { 40 return nil 41 } 42 43 if sections[sectionPartition] == "" { 44 return nil 45 } 46 if sections[sectionService] == "" { 47 return nil 48 } 49 if sections[sectionResource] == "" { 50 return nil 51 } 52 53 return &ARN{ 54 Partition: sections[sectionPartition], 55 Service: sections[sectionService], 56 Region: sections[sectionRegion], 57 AccountId: sections[sectionAccountID], 58 ResourceId: splitResource(sections[sectionResource]), 59 } 60 } 61 62 // splitResource splits the resource components by the ARN resource delimiters. 63 func splitResource(v string) []string { 64 var parts []string 65 var offset int 66 67 for offset <= len(v) { 68 idx := strings.IndexAny(v[offset:], "/:") 69 if idx < 0 { 70 parts = append(parts, v[offset:]) 71 break 72 } 73 parts = append(parts, v[offset:idx+offset]) 74 offset += idx + 1 75 } 76 77 return parts 78 } 79 80 // OptionalStringSlice provides a helper to safely get the index of a string 81 // slice that may be out of bounds. Returns pointer to string if index is 82 // valid. Otherwise returns nil. 83 type OptionalStringSlice []string 84 85 // Get returns a string pointer of the string at index i if the index is valid. 86 // Otherwise returns nil. 87 func (s OptionalStringSlice) Get(i int) *string { 88 if i < 0 || i >= len(s) { 89 return nil 90 } 91 92 v := s[i] 93 return &v 94 }