-
Notifications
You must be signed in to change notification settings - Fork 66
Expand file tree
/
Copy pathulid.go
More file actions
210 lines (176 loc) · 4.91 KB
/
ulid.go
File metadata and controls
210 lines (176 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
// SPDX-License-Identifier: Apache-2.0
package strfmt
import (
cryptorand "crypto/rand"
"database/sql/driver"
"encoding/json"
"fmt"
"io"
"sync"
"github.com/oklog/ulid/v2"
)
// ULID represents a [ulid] string format.
//
// # Reference
//
// https://github.com/ulid/spec
//
// # Implementation
//
// https://github.com/oklog/ulid
//
// swagger:strfmt ulid.
type ULID struct {
ulid.ULID
}
//nolint:gochecknoglobals // package-level ULID configuration and overridable scan/value functions
var (
ulidEntropyPool = sync.Pool{
New: func() any {
return cryptorand.Reader
},
}
// ULIDScanDefaultFunc is the default implementation for scanning a [ULID] from a database driver value.
ULIDScanDefaultFunc = func(raw any) (ULID, error) {
u := NewULIDZero()
switch x := raw.(type) {
case nil:
// zerp ulid
return u, nil
case string:
if x == "" {
// zero ulid
return u, nil
}
return u, u.UnmarshalText([]byte(x))
case []byte:
return u, u.UnmarshalText(x)
}
return u, fmt.Errorf("cannot sql.Scan() strfmt.ULID from: %#v: %w", raw, ulid.ErrScanValue)
}
// ULIDScanOverrideFunc allows you to override the Scan method of the [ULID] type.
ULIDScanOverrideFunc = ULIDScanDefaultFunc
// ULIDValueDefaultFunc is the default implementation for converting a [ULID] to a database driver value.
ULIDValueDefaultFunc = func(u ULID) (driver.Value, error) {
return driver.Value(u.String()), nil
}
// ULIDValueOverrideFunc allows you to override the Value method of the [ULID] type.
ULIDValueOverrideFunc = ULIDValueDefaultFunc
)
func init() { //nolint:gochecknoinits // registers ulid format in the default registry
ulid := ULID{}
Default.Add("ulid", &ulid, IsULID)
}
// IsULID checks if provided string is [ULID] format
// Be noticed that this function considers overflowed [ULID] as non-[ulid].
// For more details see https://github.com/[ulid]/spec
func IsULID(str string) bool {
_, err := ulid.ParseStrict(str)
return err == nil
}
// ParseULID parses a string that represents an valid [ULID].
func ParseULID(str string) (ULID, error) {
var u ULID
return u, u.UnmarshalText([]byte(str))
}
// NewULIDZero returns a zero valued [ULID] type.
func NewULIDZero() ULID {
return ULID{}
}
// NewULID generates new unique [ULID] value and a error if any.
func NewULID() (ULID, error) {
var u ULID
obj := ulidEntropyPool.Get()
entropy, ok := obj.(io.Reader)
if !ok {
return u, fmt.Errorf("failed to cast %+v to io.Reader: %w", obj, ErrFormat)
}
id, err := ulid.New(ulid.Now(), entropy)
if err != nil {
return u, err
}
ulidEntropyPool.Put(entropy)
u.ULID = id
return u, nil
}
// GetULID returns underlying instance of [ULID].
func (u *ULID) GetULID() any {
return u.ULID
}
// MarshalText returns this instance into text.
func (u ULID) MarshalText() ([]byte, error) {
return u.ULID.MarshalText()
}
// UnmarshalText hydrates this instance from text.
func (u *ULID) UnmarshalText(data []byte) error { // validation is performed later on
return u.ULID.UnmarshalText(data)
}
// Scan reads a value from a database driver.
func (u *ULID) Scan(raw any) error {
ul, err := ULIDScanOverrideFunc(raw)
if err == nil {
*u = ul
}
return err
}
// Value converts a value to a database driver value.
func (u ULID) Value() (driver.Value, error) {
return ULIDValueOverrideFunc(u)
}
func (u ULID) String() string {
return u.ULID.String()
}
// MarshalJSON returns the [ULID] as JSON.
func (u ULID) MarshalJSON() ([]byte, error) {
return json.Marshal(u.String())
}
// UnmarshalJSON sets the [ULID] from JSON.
func (u *ULID) UnmarshalJSON(data []byte) error {
if string(data) == jsonNull {
return nil
}
var ustr string
if err := json.Unmarshal(data, &ustr); err != nil {
return err
}
id, err := ulid.ParseStrict(ustr)
if err != nil {
return fmt.Errorf("couldn't parse JSON value as ULID: %w", err)
}
u.ULID = id
return nil
}
// DeepCopyInto copies the receiver and writes its value into out.
func (u *ULID) DeepCopyInto(out *ULID) {
*out = *u
}
// DeepCopy copies the receiver into a new [ULID].
func (u *ULID) DeepCopy() *ULID {
if u == nil {
return nil
}
out := new(ULID)
u.DeepCopyInto(out)
return out
}
// GobEncode implements the gob.GobEncoder interface.
func (u ULID) GobEncode() ([]byte, error) {
return u.ULID.MarshalBinary()
}
// GobDecode implements the gob.GobDecoder interface.
func (u *ULID) GobDecode(data []byte) error {
return u.ULID.UnmarshalBinary(data)
}
// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface.
func (u ULID) MarshalBinary() ([]byte, error) {
return u.ULID.MarshalBinary()
}
// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface.
func (u *ULID) UnmarshalBinary(data []byte) error {
return u.ULID.UnmarshalBinary(data)
}
// Equal checks if two [ULID] instances are equal by their underlying type.
func (u ULID) Equal(other ULID) bool {
return u.ULID == other.ULID
}