New upstream release.
Debian Janitor
2 years ago
5 | 5 | - 1.9.x |
6 | 6 | - 1.10.x |
7 | 7 | - 1.11.x |
8 | - 1.12.x | |
8 | 9 | - tip |
9 | 10 | matrix: |
10 | 11 | allow_failures: |
11 | 12 | - go: tip |
12 | 13 | fast_finish: true |
13 | env: | |
14 | - GO111MODULE=on | |
15 | 14 | before_install: |
16 | 15 | - go get golang.org/x/tools/cmd/cover |
17 | 16 | script: |
11 | 11 | |
12 | 12 | This package supports the following UUID versions: |
13 | 13 | * Version 1, based on timestamp and MAC address (RFC-4122) |
14 | * Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) | |
15 | 14 | * Version 3, based on MD5 hashing of a named value (RFC-4122) |
16 | 15 | * Version 4, based on random numbers (RFC-4122) |
17 | 16 | * Version 5, based on SHA-1 hashing of a named value (RFC-4122) |
113 | 113 | case 41, 45: |
114 | 114 | return u.decodeURN(text) |
115 | 115 | default: |
116 | return fmt.Errorf("uuid: incorrect UUID length: %s", text) | |
116 | return fmt.Errorf("uuid: incorrect UUID length %d in string %q", len(text), text) | |
117 | 117 | } |
118 | 118 | } |
119 | 119 | |
121 | 121 | // "6ba7b810-9dad-11d1-80b4-00c04fd430c8". |
122 | 122 | func (u *UUID) decodeCanonical(t []byte) error { |
123 | 123 | if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' { |
124 | return fmt.Errorf("uuid: incorrect UUID format %s", t) | |
124 | return fmt.Errorf("uuid: incorrect UUID format in string %q", t) | |
125 | 125 | } |
126 | 126 | |
127 | 127 | src := t |
159 | 159 | l := len(t) |
160 | 160 | |
161 | 161 | if t[0] != '{' || t[l-1] != '}' { |
162 | return fmt.Errorf("uuid: incorrect UUID format %s", t) | |
162 | return fmt.Errorf("uuid: incorrect UUID format in string %q", t) | |
163 | 163 | } |
164 | 164 | |
165 | 165 | return u.decodePlain(t[1 : l-1]) |
174 | 174 | urnUUIDPrefix := t[:9] |
175 | 175 | |
176 | 176 | if !bytes.Equal(urnUUIDPrefix, urnPrefix) { |
177 | return fmt.Errorf("uuid: incorrect UUID format: %s", t) | |
177 | return fmt.Errorf("uuid: incorrect UUID format in string %q", t) | |
178 | 178 | } |
179 | 179 | |
180 | 180 | return u.decodePlain(t[9:total]) |
190 | 190 | case 36: |
191 | 191 | return u.decodeCanonical(t) |
192 | 192 | default: |
193 | return fmt.Errorf("uuid: incorrect UUID length: %s", t) | |
193 | return fmt.Errorf("uuid: incorrect UUID length %d in string %q", len(t), t) | |
194 | 194 | } |
195 | 195 | } |
196 | 196 |
0 | golang-github-gofrs-uuid (4.0.0-1) UNRELEASED; urgency=low | |
1 | ||
2 | * New upstream release. | |
3 | ||
4 | -- Debian Janitor <janitor@jelmer.uk> Wed, 26 May 2021 22:18:12 -0000 | |
5 | ||
0 | 6 | golang-github-gofrs-uuid (3.2.0-2) unstable; urgency=medium |
1 | 7 | |
2 | 8 | * Standards-Version: 4.4.1 |
29 | 29 | "hash" |
30 | 30 | "io" |
31 | 31 | "net" |
32 | "os" | |
33 | 32 | "sync" |
34 | 33 | "time" |
35 | 34 | ) |
46 | 45 | // DefaultGenerator is the default UUID Generator used by this package. |
47 | 46 | var DefaultGenerator Generator = NewGen() |
48 | 47 | |
49 | var ( | |
50 | posixUID = uint32(os.Getuid()) | |
51 | posixGID = uint32(os.Getgid()) | |
52 | ) | |
53 | ||
54 | 48 | // NewV1 returns a UUID based on the current timestamp and MAC address. |
55 | 49 | func NewV1() (UUID, error) { |
56 | 50 | return DefaultGenerator.NewV1() |
57 | 51 | } |
58 | 52 | |
59 | // NewV2 returns a DCE Security UUID based on the POSIX UID/GID. | |
60 | func NewV2(domain byte) (UUID, error) { | |
61 | return DefaultGenerator.NewV2(domain) | |
62 | } | |
63 | ||
64 | 53 | // NewV3 returns a UUID based on the MD5 hash of the namespace UUID and name. |
65 | 54 | func NewV3(ns UUID, name string) UUID { |
66 | 55 | return DefaultGenerator.NewV3(ns, name) |
79 | 68 | // Generator provides an interface for generating UUIDs. |
80 | 69 | type Generator interface { |
81 | 70 | NewV1() (UUID, error) |
82 | NewV2(domain byte) (UUID, error) | |
83 | 71 | NewV3(ns UUID, name string) UUID |
84 | 72 | NewV4() (UUID, error) |
85 | 73 | NewV5(ns UUID, name string) UUID |
163 | 151 | return u, nil |
164 | 152 | } |
165 | 153 | |
166 | // NewV2 returns a DCE Security UUID based on the POSIX UID/GID. | |
167 | func (g *Gen) NewV2(domain byte) (UUID, error) { | |
168 | u, err := g.NewV1() | |
169 | if err != nil { | |
170 | return Nil, err | |
171 | } | |
172 | ||
173 | switch domain { | |
174 | case DomainPerson: | |
175 | binary.BigEndian.PutUint32(u[:], posixUID) | |
176 | case DomainGroup: | |
177 | binary.BigEndian.PutUint32(u[:], posixGID) | |
178 | } | |
179 | ||
180 | u[9] = domain | |
181 | ||
182 | u.SetVersion(V2) | |
183 | u.SetVariant(VariantRFC4122) | |
184 | ||
185 | return u, nil | |
186 | } | |
187 | ||
188 | 154 | // NewV3 returns a UUID based on the MD5 hash of the namespace UUID and name. |
189 | 155 | func (g *Gen) NewV3(ns UUID, name string) UUID { |
190 | 156 | u := newFromHash(md5.New(), ns, name) |
215 | 181 | return u |
216 | 182 | } |
217 | 183 | |
218 | // Returns the epoch and clock sequence. | |
184 | // getClockSequence returns the epoch and clock sequence. | |
219 | 185 | func (g *Gen) getClockSequence() (uint64, uint16, error) { |
220 | 186 | var err error |
221 | 187 | g.clockSequenceOnce.Do(func() { |
31 | 31 | |
32 | 32 | func TestGenerator(t *testing.T) { |
33 | 33 | t.Run("NewV1", testNewV1) |
34 | t.Run("NewV2", testNewV2) | |
35 | 34 | t.Run("NewV3", testNewV3) |
36 | 35 | t.Run("NewV4", testNewV4) |
37 | 36 | t.Run("NewV5", testNewV5) |
170 | 169 | } |
171 | 170 | } |
172 | 171 | |
173 | func testNewV2(t *testing.T) { | |
174 | t.Run("Basic", testNewV2Basic) | |
175 | t.Run("DifferentAcrossCalls", testNewV2DifferentAcrossCalls) | |
176 | t.Run("FaultyRand", testNewV2FaultyRand) | |
177 | } | |
178 | ||
179 | func testNewV2Basic(t *testing.T) { | |
180 | domains := []byte{ | |
181 | DomainPerson, | |
182 | DomainGroup, | |
183 | DomainOrg, | |
184 | } | |
185 | for _, domain := range domains { | |
186 | u, err := NewV2(domain) | |
187 | if err != nil { | |
188 | t.Errorf("NewV2(%d): %v", domain, err) | |
189 | } | |
190 | if got, want := u.Version(), V2; got != want { | |
191 | t.Errorf("NewV2(%d) generated UUID with version %d, want %d", domain, got, want) | |
192 | } | |
193 | if got, want := u.Variant(), VariantRFC4122; got != want { | |
194 | t.Errorf("NewV2(%d) generated UUID with variant %d, want %d", domain, got, want) | |
195 | } | |
196 | } | |
197 | } | |
198 | ||
199 | func testNewV2DifferentAcrossCalls(t *testing.T) { | |
200 | u1, err := NewV2(DomainOrg) | |
201 | if err != nil { | |
202 | t.Fatal(err) | |
203 | } | |
204 | u2, err := NewV2(DomainOrg) | |
205 | if err != nil { | |
206 | t.Fatal(err) | |
207 | } | |
208 | if u1 == u2 { | |
209 | t.Errorf("generated identical UUIDs across calls: %v", u1) | |
210 | } | |
211 | } | |
212 | ||
213 | func testNewV2FaultyRand(t *testing.T) { | |
214 | g := &Gen{ | |
215 | epochFunc: time.Now, | |
216 | hwAddrFunc: defaultHWAddrFunc, | |
217 | rand: &faultyReader{ | |
218 | readToFail: 0, // fail immediately | |
219 | }, | |
220 | } | |
221 | u, err := g.NewV2(DomainPerson) | |
222 | if err == nil { | |
223 | t.Fatalf("got %v, want error", u) | |
224 | } | |
225 | if u != Nil { | |
226 | t.Fatalf("got %v on error, want Nil", u) | |
227 | } | |
228 | } | |
229 | ||
230 | 172 | func testNewV3(t *testing.T) { |
231 | 173 | t.Run("Basic", testNewV3Basic) |
232 | 174 | t.Run("EqualNames", testNewV3EqualNames) |
379 | 321 | b.Run("NewV1", func(b *testing.B) { |
380 | 322 | for i := 0; i < b.N; i++ { |
381 | 323 | NewV1() |
382 | } | |
383 | }) | |
384 | b.Run("NewV2", func(b *testing.B) { | |
385 | for i := 0; i < b.N; i++ { | |
386 | NewV2(DomainOrg) | |
387 | 324 | } |
388 | 325 | }) |
389 | 326 | b.Run("NewV3", func(b *testing.B) { |
18 | 18 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
19 | 19 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
20 | 20 | |
21 | // Package uuid provides implementations of the Universally Unique Identifier (UUID), as specified in RFC-4122 and DCE 1.1. | |
21 | // Package uuid provides implementations of the Universally Unique Identifier | |
22 | // (UUID), as specified in RFC-4122, | |
22 | 23 | // |
23 | 24 | // RFC-4122[1] provides the specification for versions 1, 3, 4, and 5. |
24 | 25 | // |
25 | // DCE 1.1[2] provides the specification for version 2. | |
26 | // DCE 1.1[2] provides the specification for version 2, but version 2 support | |
27 | // was removed from this package in v4 due to some concerns with the | |
28 | // specification itself. Reading the spec, it seems that it would result in | |
29 | // generating UUIDs that aren't very unique. In having read the spec it seemed | |
30 | // that our implementation did not meet the spec. It also seems to be at-odds | |
31 | // with RFC 4122, meaning we would need quite a bit of special code to support | |
32 | // it. Lastly, there were no Version 2 implementations that we could find to | |
33 | // ensure we were understanding the specification correctly. | |
26 | 34 | // |
27 | 35 | // [1] https://tools.ietf.org/html/rfc4122 |
28 | 36 | // [2] http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 |
32 | 40 | "encoding/binary" |
33 | 41 | "encoding/hex" |
34 | 42 | "fmt" |
43 | "io" | |
44 | "strings" | |
35 | 45 | "time" |
36 | 46 | ) |
37 | 47 | |
45 | 55 | const ( |
46 | 56 | _ byte = iota |
47 | 57 | V1 // Version 1 (date-time and MAC address) |
48 | V2 // Version 2 (date-time and MAC address, DCE security version) | |
58 | _ // Version 2 (date-time and MAC address, DCE security version) [removed] | |
49 | 59 | V3 // Version 3 (namespace name-based) |
50 | 60 | V4 // Version 4 (random) |
51 | 61 | V5 // Version 5 (namespace name-based) |
67 | 77 | ) |
68 | 78 | |
69 | 79 | // Timestamp is the count of 100-nanosecond intervals since 00:00:00.00, |
70 | // 15 October 1582 within a V1 UUID. This type has no meaning for V2-V5 | |
71 | // UUIDs since they don't have an embedded timestamp. | |
80 | // 15 October 1582 within a V1 UUID. This type has no meaning for other | |
81 | // UUID versions since they don't have an embedded timestamp. | |
72 | 82 | type Timestamp uint64 |
73 | 83 | |
74 | 84 | const _100nsPerSecond = 10000000 |
155 | 165 | return string(buf) |
156 | 166 | } |
157 | 167 | |
168 | // Format implements fmt.Formatter for UUID values. | |
169 | // | |
170 | // The behavior is as follows: | |
171 | // The 'x' and 'X' verbs output only the hex digits of the UUID, using a-f for 'x' and A-F for 'X'. | |
172 | // The 'v', '+v', 's' and 'q' verbs return the canonical RFC-4122 string representation. | |
173 | // The 'S' verb returns the RFC-4122 format, but with capital hex digits. | |
174 | // The '#v' verb returns the "Go syntax" representation, which is a 16 byte array initializer. | |
175 | // All other verbs not handled directly by the fmt package (like '%p') are unsupported and will return | |
176 | // "%!verb(uuid.UUID=value)" as recommended by the fmt package. | |
177 | func (u UUID) Format(f fmt.State, c rune) { | |
178 | switch c { | |
179 | case 'x', 'X': | |
180 | s := hex.EncodeToString(u.Bytes()) | |
181 | if c == 'X' { | |
182 | s = strings.Map(toCapitalHexDigits, s) | |
183 | } | |
184 | _, _ = io.WriteString(f, s) | |
185 | case 'v': | |
186 | var s string | |
187 | if f.Flag('#') { | |
188 | s = fmt.Sprintf("%#v", [Size]byte(u)) | |
189 | } else { | |
190 | s = u.String() | |
191 | } | |
192 | _, _ = io.WriteString(f, s) | |
193 | case 's', 'S': | |
194 | s := u.String() | |
195 | if c == 'S' { | |
196 | s = strings.Map(toCapitalHexDigits, s) | |
197 | } | |
198 | _, _ = io.WriteString(f, s) | |
199 | case 'q': | |
200 | _, _ = io.WriteString(f, `"`+u.String()+`"`) | |
201 | default: | |
202 | // invalid/unsupported format verb | |
203 | fmt.Fprintf(f, "%%!%c(uuid.UUID=%s)", c, u.String()) | |
204 | } | |
205 | } | |
206 | ||
207 | func toCapitalHexDigits(ch rune) rune { | |
208 | // convert a-f hex digits to A-F | |
209 | switch ch { | |
210 | case 'a': | |
211 | return 'A' | |
212 | case 'b': | |
213 | return 'B' | |
214 | case 'c': | |
215 | return 'C' | |
216 | case 'd': | |
217 | return 'D' | |
218 | case 'e': | |
219 | return 'E' | |
220 | case 'f': | |
221 | return 'F' | |
222 | default: | |
223 | return ch | |
224 | } | |
225 | } | |
226 | ||
158 | 227 | // SetVersion sets the version bits. |
159 | 228 | func (u *UUID) SetVersion(v byte) { |
160 | 229 | u[6] = (u[6] & 0x0f) | (v << 4) |
34 | 34 | t.Run("Variant", testUUIDVariant) |
35 | 35 | t.Run("SetVersion", testUUIDSetVersion) |
36 | 36 | t.Run("SetVariant", testUUIDSetVariant) |
37 | t.Run("Format", testUUIDFormat) | |
37 | 38 | } |
38 | 39 | |
39 | 40 | func testUUIDBytes(t *testing.T) { |
109 | 110 | u.SetVariant(want) |
110 | 111 | if got := u.Variant(); got != want { |
111 | 112 | t.Errorf("%v.Variant() == %d after SetVariant(%d)", u, got, want) |
113 | } | |
114 | } | |
115 | } | |
116 | ||
117 | func testUUIDFormat(t *testing.T) { | |
118 | val := Must(FromString("12345678-90ab-cdef-1234-567890abcdef")) | |
119 | tests := []struct { | |
120 | u UUID | |
121 | f string | |
122 | want string | |
123 | }{ | |
124 | {u: val, f: "%s", want: "12345678-90ab-cdef-1234-567890abcdef"}, | |
125 | {u: val, f: "%S", want: "12345678-90AB-CDEF-1234-567890ABCDEF"}, | |
126 | {u: val, f: "%q", want: `"12345678-90ab-cdef-1234-567890abcdef"`}, | |
127 | {u: val, f: "%x", want: "1234567890abcdef1234567890abcdef"}, | |
128 | {u: val, f: "%X", want: "1234567890ABCDEF1234567890ABCDEF"}, | |
129 | {u: val, f: "%v", want: "12345678-90ab-cdef-1234-567890abcdef"}, | |
130 | {u: val, f: "%+v", want: "12345678-90ab-cdef-1234-567890abcdef"}, | |
131 | {u: val, f: "%#v", want: "[16]uint8{0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef}"}, | |
132 | {u: val, f: "%T", want: "uuid.UUID"}, | |
133 | {u: val, f: "%t", want: "%!t(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
134 | {u: val, f: "%b", want: "%!b(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
135 | {u: val, f: "%c", want: "%!c(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
136 | {u: val, f: "%d", want: "%!d(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
137 | {u: val, f: "%e", want: "%!e(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
138 | {u: val, f: "%E", want: "%!E(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
139 | {u: val, f: "%f", want: "%!f(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
140 | {u: val, f: "%F", want: "%!F(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
141 | {u: val, f: "%g", want: "%!g(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
142 | {u: val, f: "%G", want: "%!G(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
143 | {u: val, f: "%o", want: "%!o(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
144 | {u: val, f: "%U", want: "%!U(uuid.UUID=12345678-90ab-cdef-1234-567890abcdef)"}, | |
145 | } | |
146 | for _, tt := range tests { | |
147 | got := fmt.Sprintf(tt.f, tt.u) | |
148 | if tt.want != got { | |
149 | t.Errorf(`Format("%s") got %s, want %s`, tt.f, got, tt.want) | |
112 | 150 | } |
113 | 151 | } |
114 | 152 | } |