-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathuuid.go
155 lines (123 loc) · 3.08 KB
/
uuid.go
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
// Copyright 2021-2024 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0
package comid
import (
"encoding/json"
"fmt"
"github.com/google/uuid"
)
const UUIDType = "uuid"
// UUID represents an Universally Unique Identifier (UUID, see RFC4122)
type UUID uuid.UUID
// ParseUUID parses the supplied string into a UUID
func ParseUUID(s string) (UUID, error) {
v, err := uuid.Parse(s)
return UUID(v), err
}
// String returns a string representation of the binary UUID
func (o UUID) String() string {
return uuid.UUID(o).String()
}
func (o UUID) Empty() bool {
return o == (UUID{})
}
// Valid checks that the target UUID is formatted as per RFC4122
func (o UUID) Valid() error {
if variant := uuid.UUID(o).Variant(); variant != uuid.RFC4122 {
return fmt.Errorf("expecting RFC4122 UUID, got %s instead", variant)
}
return nil
}
// UnmarshalJSON deserializes the supplied string into the UUID target
// The UUID string in expected to be in canonical 8-4-4-4-12 format
func (o *UUID) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
u, err := ParseUUID(s)
if err != nil {
return fmt.Errorf("bad UUID: %w", err)
}
*o = u
return nil
}
// MarshalJSON serialize the target UUID to a JSON string in canonical
// 8-4-4-4-12 format
func (o UUID) MarshalJSON() ([]byte, error) {
return json.Marshal(o.String())
}
// TaggedUUID is an alias to allow automatic tagging of a UUID type
type TaggedUUID UUID
func NewTaggedUUID(val any) (*TaggedUUID, error) {
var ret TaggedUUID
if val == nil {
return &ret, nil
}
switch t := val.(type) {
case string:
u, err := ParseUUID(t)
if err != nil {
return nil, fmt.Errorf("bad UUID: %w", err)
}
ret = TaggedUUID(u)
case []byte:
if len(t) != 16 {
return nil, fmt.Errorf(
"unexpected size for UUID: expected 16 bytes, found %d",
len(t),
)
}
copy(ret[:], t)
case TaggedUUID:
copy(ret[:], t[:])
case *TaggedUUID:
copy(ret[:], (*t)[:])
case UUID:
copy(ret[:], t[:])
case *UUID:
copy(ret[:], (*t)[:])
case uuid.UUID:
copy(ret[:], t[:])
case *uuid.UUID:
copy(ret[:], (*t)[:])
default:
return nil, fmt.Errorf("unexpected type for UUID: %T", t)
}
if err := ret.Valid(); err != nil {
return nil, err
}
return &ret, nil
}
// String returns a string representation of the binary UUID
func (o TaggedUUID) String() string {
return UUID(o).String()
}
func (o TaggedUUID) Valid() error {
return UUID(o).Valid()
}
// Type returns a string containing type name. This is part of the
// ITypeChoiceValue implementation.
func (o TaggedUUID) Type() string {
return UUIDType
}
// Bytes returns a []byte containing the raw UUID bytes
func (o TaggedUUID) Bytes() []byte {
return o[:]
}
func (o TaggedUUID) MarshalJSON() ([]byte, error) {
temp := o.String()
return json.Marshal(temp)
}
func (o *TaggedUUID) UnmarshalJSON(data []byte) error {
var temp string
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
u, err := ParseUUID(temp)
if err != nil {
return fmt.Errorf("bad UUID: %w", err)
}
*o = TaggedUUID(u)
return nil
}