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  }