summaryrefslogtreecommitdiff
path: root/internal/id/ulid.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/id/ulid.go')
-rw-r--r--internal/id/ulid.go58
1 files changed, 34 insertions, 24 deletions
diff --git a/internal/id/ulid.go b/internal/id/ulid.go
index 04afef8f0..f763a4772 100644
--- a/internal/id/ulid.go
+++ b/internal/id/ulid.go
@@ -22,6 +22,7 @@ import (
"math/big"
"time"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/log"
"codeberg.org/gruf/go-kv/v2"
"github.com/oklog/ulid"
@@ -33,62 +34,71 @@ const (
randomRange = 631152381 // ~20 years in seconds
)
+// bigRandomRange contains randomRange as big.Int.
+var bigRandomRange = big.NewInt(randomRange)
+
// ULID represents a Universally Unique Lexicographically Sortable Identifier of 26 characters. See https://github.com/oklog/ulid
type ULID string
-// NewULID returns a new ULID string using the current time.
-func NewULID() string {
- ulid, err := ulid.New(
- ulid.Timestamp(time.Now()), rand.Reader,
- )
+// newAt returns a new ulid.ULID from timestamp,
+// else panics with caller's caller information.
+func newAt(ts uint64) string {
+ ulid, err := ulid.New(ts, rand.Reader)
if err != nil {
- panic(err)
+ panic(gtserror.NewfAt(4, "error generating ulid: %w", err))
}
return ulid.String()
}
+// NewULID returns a new ULID
+// string using the current time.
+func NewULID() string {
+ return newAt(ulid.Now())
+}
+
// NewULIDFromTime returns a new ULID string using
// given time, or from current time on any error.
func NewULIDFromTime(t time.Time) string {
ts := ulid.Timestamp(t)
if ts > ulid.MaxTime() {
log.WarnKVs(nil, kv.Fields{
- {K: "caller", V: log.Caller(2)},
+ {K: "caller", V: log.Caller(3)},
{K: "value", V: t},
{K: "msg", V: "invalid ulid time"},
}...)
ts = ulid.Now()
}
- return ulid.MustNew(ts, rand.Reader).String()
+ return newAt(ts)
}
-// NewRandomULID returns a new ULID string using a random time in an ~80 year range around the current datetime, or an error if something goes wrong.
-func NewRandomULID() (string, error) {
- b1, err := rand.Int(rand.Reader, big.NewInt(randomRange))
+// NewRandomULID returns a new ULID string using a random
+// time in an ~80 year range around the current datetime.
+func NewRandomULID() string {
+ n1, err := rand.Int(rand.Reader, bigRandomRange)
if err != nil {
- return "", err
+ panic(gtserror.NewfAt(3, "error reading rand: %w", err))
}
- r1 := time.Duration(int(b1.Int64()))
- b2, err := rand.Int(rand.Reader, big.NewInt(randomRange))
+ n2, err := rand.Int(rand.Reader, bigRandomRange)
if err != nil {
- return "", err
+ panic(gtserror.NewfAt(3, "error reading rand: %w", err))
}
- r2 := -time.Duration(int(b2.Int64()))
- arbitraryTime := time.Now().Add(r1 * time.Second).Add(r2 * time.Second)
- newUlid, err := ulid.New(ulid.Timestamp(arbitraryTime), rand.Reader)
- if err != nil {
- return "", err
- }
- return newUlid.String(), nil
+ // Random addition and decrement durations.
+ add := time.Duration(n1.Int64()) * time.Second
+ dec := -time.Duration(n2.Int64()) * time.Second
+
+ // Return new ULID string from now.
+ t := time.Now().Add(add).Add(dec)
+ return newAt(ulid.Timestamp(t))
}
+// TimeFromULID parses a ULID string and returns the
+// encoded time.Time{}, or error with caller prefix.
func TimeFromULID(id string) (time.Time, error) {
parsed, err := ulid.ParseStrict(id)
if err != nil {
- return time.Time{}, err
+ return time.Time{}, gtserror.NewfAt(3, "could not extract time (malformed ulid): %w", err)
}
-
return ulid.Time(parsed.Time()), nil
}