snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
199
server/pkg/id/id.go
Normal file
199
server/pkg/id/id.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package id
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type (
|
||||
ID struct {
|
||||
Num uint64
|
||||
Str [maxStrIdentifierLength]rune
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
maxStrIdentifierLength = 36
|
||||
)
|
||||
|
||||
var (
|
||||
isNumberRegex = regexp.MustCompile(`^(0|[1-9][0-9]{0,19})$`)
|
||||
)
|
||||
|
||||
func MustNumID(n uint64) ID {
|
||||
id, err := NumID(n)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to create NumID: %v", err))
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func NumID(n uint64) (ID, error) {
|
||||
return ID{Num: n}, nil
|
||||
}
|
||||
|
||||
func MustStrID(s string) ID {
|
||||
id, err := StrID(s)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to create StrID: %v", err))
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
func StrID(s string) (ID, error) {
|
||||
if len(s) > maxStrIdentifierLength {
|
||||
return ID{}, fmt.Errorf("string too long: %s", s)
|
||||
}
|
||||
|
||||
var str [maxStrIdentifierLength]rune
|
||||
for i, r := range s {
|
||||
if i < maxStrIdentifierLength {
|
||||
str[i] = r
|
||||
}
|
||||
}
|
||||
return ID{Str: str}, nil
|
||||
}
|
||||
|
||||
func MustByteID(data []byte) (id ID) {
|
||||
id, err := ByteID(data)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse ID: %v", err))
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func ByteID(data []byte) (id ID, err error) {
|
||||
// numeric
|
||||
if isNumberRegex.MatchString(string(data)) {
|
||||
num, err := strconv.ParseUint(string(data), 10, 64)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
id, err = NumID(num)
|
||||
return id, err
|
||||
}
|
||||
|
||||
// check if strings fit
|
||||
if len(data) > maxStrIdentifierLength {
|
||||
return id, fmt.Errorf("string too long: %s", data)
|
||||
}
|
||||
|
||||
id, err = StrID(string(data))
|
||||
return
|
||||
}
|
||||
|
||||
func (a ID) Equal(b ID) bool {
|
||||
return a == b
|
||||
}
|
||||
|
||||
func (id ID) IsZero() bool {
|
||||
return !id.isNum() && !id.isStr()
|
||||
}
|
||||
|
||||
func (id ID) isNum() bool {
|
||||
return id.Num != 0
|
||||
}
|
||||
|
||||
func (id ID) isStr() bool {
|
||||
return id.Str != [maxStrIdentifierLength]rune{}
|
||||
}
|
||||
|
||||
func InSlice(needle ID, slice ...ID) bool {
|
||||
for _, v := range slice {
|
||||
if v.Equal(needle) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RemoveFromSlice(needle ID, slice ...ID) (out []ID) {
|
||||
if len(slice) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
out = make([]ID, 0, len(slice)-1)
|
||||
|
||||
for _, i := range slice {
|
||||
if i.Equal(needle) {
|
||||
continue
|
||||
}
|
||||
|
||||
out = append(out, i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (id ID) Value() string {
|
||||
if id.isStr() {
|
||||
return `"` + string(id.String()) + `"`
|
||||
}
|
||||
|
||||
if id.isNum() {
|
||||
return `"` + String(id.Number()) + `"`
|
||||
}
|
||||
|
||||
// Backward compatibility for empty ID
|
||||
return `"0"`
|
||||
}
|
||||
|
||||
func (id ID) String() string {
|
||||
hasValid := false
|
||||
i := 0
|
||||
|
||||
for _, r := range id.Str {
|
||||
if !hasValid && r != 0 {
|
||||
hasValid = true
|
||||
continue
|
||||
}
|
||||
|
||||
if hasValid && r == 0 {
|
||||
return string(id.Str[:i+1])
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
|
||||
if !hasValid {
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(id.Str[:])
|
||||
}
|
||||
|
||||
func (id ID) Number() uint64 {
|
||||
return id.Num
|
||||
}
|
||||
|
||||
// marshal/unmarshal JSON
|
||||
func (id ID) MarshalJSON() ([]byte, error) {
|
||||
return []byte(id.Value()), nil
|
||||
}
|
||||
|
||||
func (id *ID) UnmarshalJSON(data []byte) (err error) {
|
||||
// regex to check if data contains a uint64 or smaller number
|
||||
if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
|
||||
return nil
|
||||
}
|
||||
|
||||
data = data[1 : len(data)-1]
|
||||
|
||||
auxID, err := ByteID(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
*id = auxID
|
||||
return
|
||||
}
|
||||
|
||||
func StringifySlice(bb ...ID) (out []string) {
|
||||
for _, b := range bb {
|
||||
out = append(out, b.Value())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user