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