core/internal/domain/utils.go

82 lines
1.4 KiB
Go

package domain
import (
"bytes"
"encoding/base64"
"net/url"
"strings"
)
func parseURL(rawURL string) (*url.URL, error) {
u, err := url.ParseRequestURI(rawURL)
if err != nil {
return nil, InvalidURLError{
URL: rawURL,
}
}
return u, nil
}
const (
cursorSeparator = ","
cursorKeyValueSeparator = "="
)
func encodeCursor(s [][2]string) string {
if len(s) == 0 {
return ""
}
n := len(cursorSeparator) * (len(s) - 1)
for _, el := range s {
n += len(el[0]) + len(el[1]) + len(cursorKeyValueSeparator)
}
var b bytes.Buffer
b.Grow(n)
for _, el := range s {
if b.Len() > 0 {
_, _ = b.WriteString(cursorSeparator)
}
_, _ = b.WriteString(el[0])
_, _ = b.WriteString(cursorKeyValueSeparator)
_, _ = b.WriteString(el[1])
}
return base64.StdEncoding.EncodeToString(b.Bytes())
}
const (
encodedCursorMinLength = 1
encodedCursorMaxLength = 1000
)
func decodeCursor(s string) (map[string]string, error) {
if err := validateStringLen(s, encodedCursorMinLength, encodedCursorMaxLength); err != nil {
return nil, err
}
decodedBytes, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return nil, ErrInvalidCursor
}
decoded := string(decodedBytes)
kvs := strings.Split(decoded, cursorSeparator)
m := make(map[string]string, len(kvs))
for _, kv := range kvs {
k, v, found := strings.Cut(kv, cursorKeyValueSeparator)
if !found {
return nil, ErrInvalidCursor
}
m[k] = v
}
return m, nil
}