github.com/clubpay/ronykit/kit@v0.14.4-0.20240515065620-d0dace45cbc7/utils/srl/srl.go (about) 1 package srl 2 3 import ( 4 "regexp" 5 "strings" 6 ) 7 8 const ( 9 pathGlue = ":" 10 glue = "@" 11 ) 12 13 const ( 14 srliStorage = iota 15 srliPath 16 srliID 17 18 srlLength 19 ) 20 21 var pattern = regexp.MustCompile(`(?:([^:\s]*):)?([^@\s]*)@?(.*)`) 22 23 // SRL stands for Simple Resource Locator, A 3 part address. 24 type SRL [srlLength]string 25 26 // New creates a SRL of path & id on a specific storage. 27 func New(storage, path, id string) SRL { 28 return SRL{storage, path, id} 29 } 30 31 // Portable creates a SRL of path & id on unspecific storage. 32 func Portable(path, id string) SRL { 33 return New("", path, id) 34 } 35 36 // Storage creates a SRL without any path & id on a specific storage. 37 func Storage(storage string) SRL { 38 return New(storage, "", "") 39 } 40 41 func Parse(str string) SRL { 42 q := SRL{} 43 44 mm := pattern.FindAllStringSubmatch(str, -1) 45 if len(mm) == 0 { 46 return q 47 } 48 49 pp := mm[0] 50 for i := srlLength; i > 0; i-- { 51 if len(pp) > i { 52 q[i-1] = pp[i] 53 } 54 } 55 56 return q 57 } 58 59 // Append returns a new SRL with non-empty fields of src appended to it. 60 // It joins paths if available on both q & src with pathGlue 61 func (q SRL) Append(src SRL) SRL { 62 return q.mix( 63 src, 64 func(qi, si string, i int) string { 65 if len(si) == 0 { 66 return qi 67 } 68 69 if srliPath == i && len(qi) > 0 { 70 return strings.Join([]string{qi, si}, pathGlue) 71 } 72 73 return si 74 }, 75 ) 76 } 77 78 // Merge returns a new SRL with fields replaced by non-empty src fields. 79 func (q SRL) Merge(src SRL) SRL { 80 return q.mix( 81 src, 82 func(qi, si string, i int) string { 83 if len(si) == 0 { 84 return qi 85 } 86 87 return si 88 }, 89 ) 90 } 91 92 // Replace returns a new SRL with all fields replaced by src fields. 93 func (q SRL) Replace(src SRL) SRL { 94 return q.mix( 95 src, 96 func(qi, si string, i int) string { 97 return si 98 }, 99 ) 100 } 101 102 func (q SRL) mix(src SRL, fn func(qi, si string, i int) string) SRL { 103 for i := 0; i < srlLength; i++ { 104 q[i] = fn(q[i], src[i], i) 105 } 106 107 return q 108 } 109 110 func (q SRL) String() string { 111 var sb strings.Builder 112 113 for i := 0; i < srlLength; i++ { 114 pglue, sglue := "", "" 115 116 switch i { 117 case srliStorage: 118 sglue = pathGlue 119 120 case srliID: 121 pglue = glue 122 } 123 124 p := q[i] 125 if l := len(p); l > 0 { 126 sb.Grow(l + 1) 127 sb.WriteString(pglue) 128 sb.WriteString(p) 129 sb.WriteString(sglue) 130 } 131 } 132 133 return sb.String() 134 } 135 136 func (q SRL) Storage() string { 137 return q[srliStorage] 138 } 139 140 func (q SRL) Path() string { 141 return q[srliPath] 142 } 143 144 func (q SRL) ID() string { 145 return q[srliID] 146 }