Skip to content

Commit

Permalink
Use sync.OnceValue only on go1.21+
Browse files Browse the repository at this point in the history
sync.OnceValue was introduced in go1.21. Currently validator's go.mod
states minimum go version to be go1.18.

This commit moves the lazy regex initialization into its own file
lazy.go and provides backwards compatibility using buildtags and the
file lazy_compat.go which contains a backported (non-generic) version of
sync.OnceValue.

Signed-off-by: Kimmo Lehto <[email protected]>
  • Loading branch information
kke committed Jun 13, 2024
1 parent c111ad2 commit 45664ca
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 11 deletions.
14 changes: 14 additions & 0 deletions lazy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build go1.21

package validator

import (
"regexp"
"sync"
)

func lazyRegexCompile(str string) func() *regexp.Regexp {
return sync.OnceValue(func() *regexp.Regexp {
return regexp.MustCompile(str)
})
}
46 changes: 46 additions & 0 deletions lazy_compat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//go:build !go1.21

package validator

import (
"regexp"
"sync"
)

// Copied and adapted from go1.21 stdlib's sync.OnceValue for backwards compatibility:
// OnceValue returns a function that invokes f only once and returns the value
// returned by f. The returned function may be called concurrently.
//
// If f panics, the returned function will panic with the same value on every call.
func onceValue(f func() *regexp.Regexp) func() *regexp.Regexp {
var (
once sync.Once
valid bool
p any

Check failure on line 19 in lazy_compat.go

View workflow job for this annotation

GitHub Actions / test (1.17.x, ubuntu-latest)

undefined: any
result *regexp.Regexp
)
g := func() {
defer func() {
p = recover()
if !valid {
panic(p)
}
}()
result = f()
f = nil
valid = true
}
return func() *regexp.Regexp {
once.Do(g)
if !valid {
panic(p)
}
return result
}
}

func lazyRegexCompile(str string) func() *regexp.Regexp {
return onceValue(func() *regexp.Regexp {
return regexp.MustCompile(str)
})
}
11 changes: 0 additions & 11 deletions regexes.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package validator

import (
"regexp"
"sync"
)

const (
alphaRegexString = "^[a-zA-Z]+$"
alphaNumericRegexString = "^[a-zA-Z0-9]+$"
Expand Down Expand Up @@ -79,12 +74,6 @@ const (
spicedbTypeRegexString = "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$"
)

func lazyRegexCompile(str string) func() *regexp.Regexp {
return sync.OnceValue(func() *regexp.Regexp {
return regexp.MustCompile(str)
})
}

var (
alphaRegex = lazyRegexCompile(alphaRegexString)
alphaNumericRegex = lazyRegexCompile(alphaNumericRegexString)
Expand Down

0 comments on commit 45664ca

Please sign in to comment.