Skip to content

Commit a24fe43

Browse files
Domas Monkus0x2b3bfa0
andauthored
Identifiers with configurable prefixes. (#727)
Co-authored-by: Helio Machado <0x2b3bfa0+git@googlemail.com>
1 parent c681e1e commit a24fe43

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

task/common/identifier.go

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,56 +10,73 @@ import (
1010
"crypto/sha256"
1111

1212
"github.com/aohorodnyk/uid"
13-
"github.com/dustinkirkland/golang-petname"
13+
petname "github.com/dustinkirkland/golang-petname"
1414
)
1515

1616
type Identifier struct {
17-
name string
18-
salt string
17+
prefix string
18+
name string
19+
salt string
1920
}
2021

2122
var ErrWrongIdentifier = errors.New("wrong identifier")
2223

2324
const (
24-
maximumLongLength = 50
25-
shortLength = 16
26-
nameLength = maximumLongLength-shortLength-uint32(len("tpi---"))
25+
defaultIdentifierPrefix = "tpi"
26+
maximumLongLength = 50
27+
shortLength = 16
28+
nameLength = maximumLongLength - shortLength - uint32(len("tpi---"))
2729
)
2830

31+
// ParseIdentifier parses the string representation of the identifier.
2932
func ParseIdentifier(identifier string) (Identifier, error) {
30-
re := regexp.MustCompile(`(?s)^tpi-([a-z0-9]+(?:[a-z0-9-]*[a-z0-9])?)-([a-z0-9]+)-([a-z0-9]+)$`)
33+
re := regexp.MustCompile(`(?s)^([a-z0-9]{3})-([a-z0-9]+(?:[a-z0-9-]*[a-z0-9])?)-([a-z0-9]+)-([a-z0-9]+)$`)
3134

32-
if match := re.FindStringSubmatch(string(identifier)); len(match) > 0 && hash(match[1]+match[2], shortLength/2) == match[3] {
33-
return Identifier{name: match[1], salt: match[2]}, nil
35+
if match := re.FindStringSubmatch(string(identifier)); len(match) > 0 && hash(match[2]+match[3], shortLength/2) == match[4] {
36+
return Identifier{prefix: match[1], name: match[2], salt: match[3]}, nil
3437
}
3538

3639
return Identifier{}, ErrWrongIdentifier
3740
}
3841

42+
// NewDeterministicIdentifierWithPrefix returns a new deterministic Identifier, with
43+
// the specified prefix, using the provided name as a seed. Repeated calls to this
44+
// function are guaranteed to generate the same Identifier.
45+
func NewDeterministicIdentifierWithPrefix(prefix, name string) Identifier {
46+
seed := normalize(name, nameLength)
47+
return Identifier{prefix: prefix[0:3], name: name, salt: hash(seed, shortLength/2)}
48+
}
49+
3950
// NewDeterministicIdentifier returns a new deterministic Identifier, using the
4051
// provided name as a seed. Repeated calls to this function are guaranteed to
4152
// generate the same Identifier.
4253
func NewDeterministicIdentifier(name string) Identifier {
43-
seed := normalize(name, nameLength)
44-
return Identifier{name: name, salt: hash(seed, shortLength/2)}
54+
return NewDeterministicIdentifierWithPrefix(defaultIdentifierPrefix, name)
4555
}
4656

47-
// NewRandomIdentifier returns a new random Identifier. Repeated calls to this
48-
// function are guaranteed to generate different Identifiers, as long as there
49-
// are no collisions.
50-
func NewRandomIdentifier(name string) Identifier {
57+
// NewRandomIdentifierWithPrefix returns a new random Identifier with the
58+
// specified prefix. Only the first 3 symbols of the prefix are used.
59+
// Repeated calls to this function are guaranteed to generate different
60+
// Identifiers, as long as there are no collisions.
61+
func NewRandomIdentifierWithPrefix(prefix, name string) Identifier {
5162
seed := uid.NewProvider36Size(8).MustGenerate().String()
5263
if name == "" {
5364
petname.NonDeterministicMode()
5465
name = petname.Generate(3, "-")
5566
}
67+
return Identifier{prefix: prefix[0:3], name: name, salt: hash(seed, shortLength/2)}
68+
}
5669

57-
return Identifier{name: name, salt: hash(seed, shortLength/2)}
70+
// NewRandomIdentifier returns a new random Identifier.
71+
// Repeated calls to this function are guaranteed to generate different
72+
// Identifiers, as long as there are no collisions.
73+
func NewRandomIdentifier(name string) Identifier {
74+
return NewRandomIdentifierWithPrefix(defaultIdentifierPrefix, name)
5875
}
5976

6077
func (i Identifier) Long() string {
6178
name := normalize(i.name, nameLength)
62-
return fmt.Sprintf("tpi-%s-%s-%s", name, i.salt, hash(name+i.salt, shortLength/2))
79+
return fmt.Sprintf("%s-%s-%s-%s", i.prefix, name, i.salt, hash(name+i.salt, shortLength/2))
6380
}
6481

6582
func (i Identifier) Short() string {

task/common/identifier_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func TestIdentifier(t *testing.T) {
5151

5252
t.Run("randomness", func(t *testing.T) {
5353
name := "test"
54-
54+
5555
first := NewRandomIdentifier(name)
5656
second := NewRandomIdentifier(name)
5757

@@ -61,4 +61,15 @@ func TestIdentifier(t *testing.T) {
6161
require.Contains(t, first.Long(), name)
6262
require.Contains(t, second.Long(), name)
6363
})
64+
65+
t.Run("prefix", func(t *testing.T) {
66+
identifier := NewDeterministicIdentifierWithPrefix("ipsum", "test")
67+
68+
require.Equal(t, "ips-test-3z4xlzwq-3u0vweb4", identifier.Long())
69+
require.Equal(t, "3z4xlzwq3u0vweb4", identifier.Short())
70+
71+
parsed, err := ParseIdentifier(identifier.Long())
72+
require.Equal(t, parsed.Long(), identifier.Long())
73+
require.NoError(t, err)
74+
})
6475
}

0 commit comments

Comments
 (0)