uuid-ncname 0.3.1 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d17bfbafda1f25ed22fe1b314af7d9add89e66caa92a5f859fe399b81b4a1c63
4
- data.tar.gz: 38372398d6460a72212023f6904c2eef6b5785461169f8ff7e1ff4248aa08ea2
3
+ metadata.gz: 95ef04d6f41f5d6b98fc5dbd814ef77d7b24e845b212a20fe73a79b2914d2cb0
4
+ data.tar.gz: ca0c34414228e1aba0b9d430d322bd8a62d533fcc93586a8735f7d64412aac24
5
5
  SHA512:
6
- metadata.gz: c2f4d687ce200545784b6cd57417d182701faa805bb11e963184418284bc134b02e191a099026a63183aad8f089fd9eb140331fcd3915f33a1ea5e596e97836a
7
- data.tar.gz: dcbd3afa99943709d07892fff109659dc567fbb3c7ab285cd5b9281894cb0477d984fd9ca0de12b778bd4d7125643299ce9ac61047fbd3a22ce35a91bb774722
6
+ metadata.gz: ba2311769361dc7646e354afdf58421e4b2e8f2f3e57780edb340dc9a45900958b793c5ac2bbe0fff124f364b922ff700a2867cbdd74108e7f31cc40255c431a
7
+ data.tar.gz: d0cfeb74e954dd45b0322771327f022040f8fbe22bebb47ef688b970e790b4d7966a8eb418c5fa8ee097b66d08fb73854355c71d255fb8c1c0d53fbc3b360f89
data/README.md CHANGED
@@ -7,19 +7,17 @@ require 'uuidtools'
7
7
  uu = UUIDTools::UUID.random_create
8
8
  # => #<UUID:0x3fff0e597ef8 UUID:df521e0a-9d57-4f04-9a95-fc2888decc5a>
9
9
 
10
- # see below about this :version parameter
11
-
12
- nc64 = UUID::NCName.to_ncname uu, version: 1
10
+ nc64 = UUID::NCName.to_ncname uu
13
11
  # => "E31IeCp1X8EqV_CiI3sxaJ"
14
12
 
15
- nc32 = UUID::NCName.to_ncname_32 uu, version: 1
13
+ nc32 = UUID::NCName.to_ncname_32 uu
16
14
  # => "E35jb4cu5k7yevfp4fcen5tc2j"
17
15
 
18
- orig = UUID::NCName.from_ncname nc64, version: 1
16
+ orig = UUID::NCName.from_ncname nc64
19
17
  # => "df521e0a-9d57-4f04-9a95-fc2888decc5a"
20
18
 
21
- orig == UUID::NCName.from_ncname nc32, version: 1 # => true
22
- orig == uu.to_s # => true
19
+ orig == UUID::NCName.from_ncname nc32 # => true
20
+ orig == uu.to_s # => true
23
21
 
24
22
  # then you can turn it back into an object or whatever
25
23
  uu == UUIDTools::UUID.parse(orig) # => true
@@ -27,69 +25,12 @@ uu == UUIDTools::UUID.parse(orig) # => true
27
25
 
28
26
  ## Description
29
27
 
30
- The purpose of this module is to devise an alternative representation
28
+ The purpose of this module is to [devise an alternative
29
+ representation](https://datatracker.ietf.org/doc/html/draft-taylor-uuid-ncname)
31
30
  of the [UUID](http://tools.ietf.org/html/rfc4122) which conforms to
32
- the constraints of various other identifiers such as NCName, and create an
33
- [isomorphic](http://en.wikipedia.org/wiki/Isomorphism) mapping between
34
- them.
35
-
36
- ## _FORMAT DEPRECATION NOTICE_
37
-
38
- After careful consideration, I have decided to change the UUID-NCName
39
- format in a minor yet incompatible way. In particular, I have moved
40
- the nybble containing
41
- the [`variant`](https://tools.ietf.org/html/rfc4122#section-4.1.1) to
42
- the very end of the identifier, whereas it previously was mixed into
43
- the middle somewhere.
44
-
45
- This can be considered an application
46
- of [Postel's Law](https://en.wikipedia.org/wiki/Postel%27s_law), based
47
- on the assumption that these identifiers will be generated through
48
- other methods, and potentially naïvely. Like the `version` field, the
49
- `variant` field has a limited acceptable range of values. If, for
50
- example, one were to attempt to generate a conforming identifier by
51
- simply generating a random Base32 or Base64 string, it will be
52
- difficult to ensure that the `variant` field will indeed conform when
53
- the identifier is converted to a standard UUID. By moving the
54
- `variant` field out to the end of the identifier, everything between
55
- the `version` and `variant` bookends can be generated randomly without
56
- any further consideration, like so:
57
-
58
- ```ruby
59
- B64_ALPHA = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + %w(- _)
60
-
61
- def make_cheapo_b64_uuid_ncname
62
- vals = (1..20).map { rand 64 } # generate the content
63
- vals.push(rand(4) + 8) # last digit is special
64
- 'E' + vals.map { |v| B64_ALPHA[v] }.join('') # 'E' for UUID v4
65
- end
66
-
67
- # voilà:
68
-
69
- cheap = make_cheapo_b64_uuid_ncname
70
- # => "EXSVv8ezPbSKWoKOkBNWKL"
71
-
72
- # now try changing it to a standard UUID:
73
-
74
- UUID::NCName.from_ncname cheap, version: 1
75
- # => "5d256ff1-eccf-46d2-b296-a0a3a404d58a"
76
- ```
77
-
78
- Furthermore, since the default behaviour is to align the bits of the
79
- last byte to the size of the encoding symbol, and since the `variant`
80
- bits are masked, a compliant RFC4122 UUID will _always_ end with `I`,
81
- `J`, `K`, or `L`, in _both_ Base32 (case-insensitive) and Base64
82
- variants.
83
-
84
- Since I have already released this gem prior to this format change, I
85
- have added a `:version` parameter to both `to_ncname` and
86
- `from_ncname`. The version, as of 0.2.4, now defaults to `1`, the
87
- current one, but will still issue a warning if not explicitly
88
- set. Later I will finally remove the warning. This should ensure that
89
- any code written during the transition produces the correct results.
90
-
91
- > Unless you have to support identifiers generated from version 0.1.3
92
- > or older, you should be running these methods with `version: 1`.
31
+ the constraints of various other identifiers such as NCName, and
32
+ create an [isomorphic](http://en.wikipedia.org/wiki/Isomorphism)
33
+ mapping between them.
93
34
 
94
35
  ## Rationale & Method
95
36
 
@@ -198,6 +139,62 @@ representation should be adequate for placeholder symbols in just
198
139
  about any programming language, save for those which do not permit
199
140
  identifiers as long as 26 characters (which are extremely scarce).
200
141
 
142
+ ## _FORMAT DEPRECATION NOTICE_
143
+
144
+ After careful consideration, I have decided to change the UUID-NCName
145
+ format in a minor yet incompatible way. In particular, I have moved
146
+ the nybble containing
147
+ the [`variant`](https://tools.ietf.org/html/rfc4122#section-4.1.1) to
148
+ the very end of the identifier, whereas it previously was mixed into
149
+ the middle somewhere.
150
+
151
+ This can be considered an application
152
+ of [Postel's Law](https://en.wikipedia.org/wiki/Postel%27s_law), based
153
+ on the assumption that these identifiers will be generated through
154
+ other methods, and potentially naïvely. Like the `version` field, the
155
+ `variant` field has a limited acceptable range of values. If, for
156
+ example, one were to attempt to generate a conforming identifier by
157
+ simply generating a random Base32 or Base64 string, it will be
158
+ difficult to ensure that the `variant` field will indeed conform when
159
+ the identifier is converted to a standard UUID. By moving the
160
+ `variant` field out to the end of the identifier, everything between
161
+ the `version` and `variant` bookends can be generated randomly without
162
+ any further consideration, like so:
163
+
164
+ ```ruby
165
+ B64_ALPHA = ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + %w(- _)
166
+
167
+ def make_cheapo_b64_uuid_ncname
168
+ vals = (1..20).map { rand 64 } # generate the content
169
+ vals.push(rand(4) + 8) # last digit is special
170
+ 'E' + vals.map { |v| B64_ALPHA[v] }.join('') # 'E' for UUID v4
171
+ end
172
+
173
+ # voilà:
174
+
175
+ cheap = make_cheapo_b64_uuid_ncname
176
+ # => "EXSVv8ezPbSKWoKOkBNWKL"
177
+
178
+ # now try changing it to a standard UUID:
179
+
180
+ UUID::NCName.from_ncname cheap, version: 1
181
+ # => "5d256ff1-eccf-46d2-b296-a0a3a404d58a"
182
+ ```
183
+
184
+ Furthermore, since the default behaviour is to align the bits of the
185
+ last byte to the size of the encoding symbol, and since the `variant`
186
+ bits are masked, a compliant RFC4122 UUID will _always_ end with `I`,
187
+ `J`, `K`, or `L`, in _both_ Base32 (case-insensitive) and Base64
188
+ variants.
189
+
190
+ Since I have already released this gem prior to this format change, I
191
+ have added a `:version` parameter to both `to_ncname` and
192
+ `from_ncname`. This parameter, which controls the compact UUID spec
193
+ behaviour, defaults to `1`, as of the _module_ version 0.2.4.
194
+
195
+ > Unless you have to support identifiers generated from version 0.1.3
196
+ > or older, you should be running these methods with `version: 1`.
197
+
201
198
  ## Documentation
202
199
 
203
200
  Generated and deposited
@@ -6,5 +6,5 @@ unless Module.const_defined? 'UUID'
6
6
  end
7
7
 
8
8
  module UUID::NCName
9
- VERSION = "0.3.1"
9
+ VERSION = "0.4.1"
10
10
  end
data/lib/uuid/ncname.rb CHANGED
@@ -61,8 +61,11 @@ module UUID::NCName
61
61
  },
62
62
  58 => -> (str, _) {
63
63
  variant = decode_version(str[-1]) << 4
64
+ # warn str
64
65
  str = str.chop.tr ?_, ''
65
- ::Base58.base58_to_binary(str, :bitcoin) + variant.chr
66
+ # warn str
67
+ # warn ::Base58.base58_to_binary(str, :bitcoin).length
68
+ ::Base58.base58_to_binary(str, :bitcoin) + variant.chr.b
66
69
  },
67
70
  64 => -> (str, align = true) {
68
71
  str = str[0, 21] + 'A=='
@@ -77,6 +80,7 @@ module UUID::NCName
77
80
 
78
81
  FORMAT = {
79
82
  str: -> bin { UUF % bin.unpack('C*') },
83
+ urn: -> bin { "urn:uuid:#{UUF % bin.unpack('C*')}" },
80
84
  hex: -> bin { bin.unpack 'H*' },
81
85
  b64: -> bin { ::Base64.strict_encode64 bin },
82
86
  bin: -> bin { bin },
@@ -125,7 +129,10 @@ module UUID::NCName
125
129
  -> (version, data) {
126
130
  version &= 0xf
127
131
 
132
+ # warn data.length
133
+
128
134
  list = data.unpack 'N4'
135
+ # warn list.inspect
129
136
  variant = (list[3] & 0xf0) << 24
130
137
  list[3] >>= 8
131
138
  list[3] |= ((list[2] & 0xff) << 24)
@@ -148,6 +155,16 @@ module UUID::NCName
148
155
  (version.upcase.ord - 65) % 16
149
156
  end
150
157
 
158
+ def self.assert_version version
159
+ version = 1 unless version
160
+ raise ArgumentError, "version #{version.inspect} is not an integer" unless
161
+ version.respond_to? :to_i
162
+ version = version.to_i
163
+ raise ArgumentError, "there is no version #{version}" unless
164
+ TRANSFORM[version]
165
+ version
166
+ end
167
+
151
168
  def self.warn_version version
152
169
  if version.nil?
153
170
  warn 'Set an explicit :version to remove this warning. See documentation.'
@@ -194,10 +211,8 @@ module UUID::NCName
194
211
  #
195
212
  # @param version [0, 1] An optional formatting version, where 0 is
196
213
  # the naïve original version and 1 moves the `variant` nybble out
197
- # to the end of the identifier. You will be warned for the time
198
- # being if you do not set this parameter explicitly. The default
199
- # version is 1.
200
- #
214
+ # to the end of the identifier. The default version is 1.
215
+ #
201
216
  # @param align [true, false] Optional directive to treat the
202
217
  # terminating character as aligned to the numerical base of the
203
218
  # representation. Since the version nybble is removed from the
@@ -209,7 +224,7 @@ module UUID::NCName
209
224
  # and the terminating character is aligned, RFC4122-compliant UUIDs
210
225
  # will always terminate with `I`, `J`, `K`, or `L`. Defaults to
211
226
  # `true`.
212
- #
227
+ #
213
228
  # @return [String] The NCName-formatted UUID.
214
229
  #
215
230
  def self.to_ncname uuid, radix: 64, version: nil, align: true
@@ -220,7 +235,8 @@ module UUID::NCName
220
235
  align = !!align # coerce to a boolean
221
236
 
222
237
  # XXX remove this when appropriate
223
- version = warn_version(version)
238
+ # version = warn_version(version)
239
+ version = assert_version version
224
240
 
225
241
  uuid = uuid.to_s
226
242
  bin = nil
@@ -228,7 +244,7 @@ module UUID::NCName
228
244
  if uuid.length == 16
229
245
  bin = uuid
230
246
  else
231
- uuid.gsub!(/\s+/, '')
247
+ uuid = uuid.gsub(/\s+/, '')
232
248
  if (m = /^(?:urn:uuid:)?([0-9A-Fa-f-]{32,})$/.match(uuid))
233
249
  bin = [m[1].tr('-', '')].pack 'H*'
234
250
  elsif (m = /^([0-9A-Za-z+\/_-]+=*)$/.match(uuid))
@@ -253,14 +269,15 @@ module UUID::NCName
253
269
  #
254
270
  # @param ncname [#to_s] an NCName-encoded UUID, either a
255
271
  # 22-character (Base64) variant, or a 26-character (Base32) variant.
256
- #
257
- # @param radix [nil, 32, 64] Optional radix; will use heuristic if omitted.
258
272
  #
259
- # @param format [:str, :hex, :b64, :bin] An optional formatting
273
+ # @param radix [nil, 32, 58, 64] Optional radix; will use a heuristic
274
+ # if omitted.
275
+ #
276
+ # @param format [:str, :urn, :hex, :b64, :bin] An optional formatting
260
277
  # parameter; defaults to `:str`, the canonical string representation.
261
278
  #
262
279
  # @param version [0, 1] See ::to_ncname. Defaults to 1.
263
- #
280
+ #
264
281
  # @param align [nil, true, false] See ::to_ncname for details.
265
282
  # Setting this parameter to `nil`, the default, will cause the
266
283
  # decoder to detect the alignment state from the identifier.
@@ -279,7 +296,8 @@ module UUID::NCName
279
296
  [true, false, nil].include? align
280
297
 
281
298
  # XXX remove this when appropriate
282
- version = warn_version version
299
+ # version = warn_version version
300
+ version = assert_version version
283
301
 
284
302
  return unless ncname and ncname.respond_to? :to_s
285
303
 
@@ -317,9 +335,9 @@ module UUID::NCName
317
335
  # Shorthand for conversion to the Base64 version
318
336
  #
319
337
  # @param uuid [#to_s] The UUID
320
- #
338
+ #
321
339
  # @param version [0, 1] See ::to_ncname.
322
- #
340
+ #
323
341
  # @param align [true, false] See ::to_ncname.
324
342
  #
325
343
  # @return [String] The Base64-encoded NCName
@@ -333,24 +351,25 @@ module UUID::NCName
333
351
  # @param ncname [#to_s] The Base64 variant of the NCName-encoded UUID
334
352
  #
335
353
  # @param format [:str, :hex, :b64, :bin] The format
336
- #
354
+ #
337
355
  # @param version [0, 1] See ::to_ncname.
338
- #
356
+ #
339
357
  # @param align [true, false] See ::to_ncname.
340
358
  #
341
359
  # @return [String, nil] The corresponding UUID or nil if the input
342
360
  # is malformed.
343
361
  #
344
362
  def self.from_ncname_64 ncname, format: :str, version: nil, align: nil
345
- from_ncname ncname, radix: 64, format: format
363
+ from_ncname ncname,
364
+ radix: 64, format: format, version: version, align: align
346
365
  end
347
366
 
348
367
  # Shorthand for conversion to the Base58 version
349
368
  #
350
369
  # @param uuid [#to_s] The UUID
351
- #
370
+ #
352
371
  # @param version [0, 1] See ::to_ncname.
353
- #
372
+ #
354
373
  # @param align [true, false] See ::to_ncname.
355
374
  #
356
375
  # @return [String] The Base58-encoded NCName
@@ -364,24 +383,25 @@ module UUID::NCName
364
383
  # @param ncname [#to_s] The Base58 variant of the NCName-encoded UUID
365
384
  #
366
385
  # @param format [:str, :hex, :b64, :bin] The format
367
- #
386
+ #
368
387
  # @param version [0, 1] See ::to_ncname.
369
- #
388
+ #
370
389
  # @param align [true, false] See ::to_ncname.
371
390
  #
372
391
  # @return [String, nil] The corresponding UUID or nil if the input
373
392
  # is malformed.
374
393
  #
375
394
  def self.from_ncname_58 ncname, format: :str, version: nil, align: nil
376
- from_ncname ncname, radix: 58, format: format
395
+ from_ncname ncname,
396
+ radix: 58, format: format, version: version, align: align
377
397
  end
378
398
 
379
399
  # Shorthand for conversion to the Base32 version
380
400
  #
381
401
  # @param uuid [#to_s] The UUID
382
- #
402
+ #
383
403
  # @param version [0, 1] See ::to_ncname.
384
- #
404
+ #
385
405
  # @param align [true, false] See ::to_ncname.
386
406
  #
387
407
  # @return [String] The Base32-encoded NCName
@@ -395,16 +415,17 @@ module UUID::NCName
395
415
  # @param ncname [#to_s] The Base32 variant of the NCName-encoded UUID
396
416
  #
397
417
  # @param format [:str, :hex, :b64, :bin] The format
398
- #
418
+ #
399
419
  # @param version [0, 1] See ::to_ncname.
400
- #
420
+ #
401
421
  # @param align [true, false] See ::to_ncname.
402
422
  #
403
423
  # @return [String, nil] The corresponding UUID or nil if the input
404
424
  # is malformed.
405
425
  #
406
426
  def self.from_ncname_32 ncname, format: :str, version: nil, align: nil
407
- from_ncname ncname, radix: 32, format: format
427
+ from_ncname ncname,
428
+ radix: 32, format: format, version: version, align: align
408
429
  end
409
430
 
410
431
  # Test if the given token is a UUID NCName, with a hint to its
@@ -430,7 +451,7 @@ module UUID::NCName
430
451
  # false is definitely version zero but true is only maybe version 1
431
452
  version = /^(?:.{21}[I-L]|.{25}[I-Li-l])$/.match(token) ? 1 : 0
432
453
 
433
- # try decoding with validation on
454
+ # try decoding with validation on
434
455
  uu = from_ncname token, version: version, validate: true
435
456
 
436
457
  # note that version 1 will always return something because the
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'uuid-ncname'
4
+ require 'csv'
5
+ require 'pathname'
6
+ require 'uuidtools'
7
+
8
+ out = Pathname(ARGV.first).expand_path
9
+
10
+ CSV.open(out, 'wb') do |csv|
11
+ uuids = []
12
+ 1000.times { uuids << UUIDTools::UUID.random_create }
13
+
14
+ # do the version first
15
+ (0..1).each do |v|
16
+ # then he radices
17
+ uuids.each do |u|
18
+ row = [v, u.to_s]
19
+
20
+ [32, 58, 64].each do |r|
21
+ row << UUID::NCName.to_ncname(u, radix: r, version: v)
22
+ end
23
+
24
+ csv << row
25
+ end
26
+ end
27
+ end
28
+