uuid-ncname 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f82febb1e1498f1d602bd2225b730b7e9128b7ea7b811472465001ae9925e83d
4
- data.tar.gz: 8f403882f98f9509c074e3b53c1aebe58ff0b0adbe9f248baf4df9ded59b7b25
3
+ metadata.gz: 5949f2dc85dabebd7eca564905e35a5e81c9c0d28b5801f4796c07ab177035fe
4
+ data.tar.gz: 8d8fc2c39629b9135e7fbd36d6395a638e5a88f64cea7b09ba78c832d8a9eb08
5
5
  SHA512:
6
- metadata.gz: b0c1948dd81504cd7241f2a5ad78e50f661b4d9b0868402fd3e393760a5ddf6d30be82f39b51d700e0ded7681efa65134fb0e37ffa27f2108c238ccb8d2cbdfe
7
- data.tar.gz: 2c86dfc2b5ee4b1c1be7c1e8343e844bfa9df0a94ebf20b487fd5988b53df4e138ae05e44d5134b00c4e1092140d24042c3e1c5d90ad9238a87fea65ab165f3c
6
+ metadata.gz: 749c76afe8ca6edc6fc563b8496c97a1c25bcaa956c287181d039b219da25d196ea9d9b2736ecd8f7a81645bc82cc835ddf0d0062f40817dc038e5011833d265
7
+ data.tar.gz: 429ec2d8d45e7815fd775d03ce9c327996321f44dd3ef7a0cf6e880c161ed07fd9f513249f6e16961e7b3d84af043bc55080ba1d4ced8fa64a46f22b4eab7f9a
data/.gitignore CHANGED
@@ -8,6 +8,8 @@ syntax: glob
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  *.gem
11
+ \#*
12
+ .\#*
11
13
 
12
14
  # rspec failure tracking
13
15
  .rspec_status
@@ -0,0 +1,5 @@
1
+ --protected
2
+ --no-private
3
+ --hide-void-return
4
+ --markup markdown
5
+ --readme README.md
@@ -3,11 +3,20 @@ require "uuid/ncname/version"
3
3
 
4
4
  require 'base64'
5
5
  require 'base32'
6
+ require 'base58'
6
7
 
7
8
  module UUID::NCName
8
9
 
9
10
  private
10
11
 
12
+ MATCH = /^([A-Pa-p]) # zero-width boundary and version bookend
13
+ ([2-7A-Za-z]{24}|[-0-9A-Z_a-z]{20}| # base32 and 64
14
+ (?:[1-9A-HJ-NP-Za-z]{15}_{6}|[1-9A-HJ-NP-Za-z]{16}_{5}|
15
+ [1-9A-HJ-NP-Za-z]{17}_{4}|[1-9A-HJ-NP-Za-z]{18}___|
16
+ [1-9A-HJ-NP-Za-z]{19}__|[1-9A-HJ-NP-Za-z]{20}_|
17
+ [1-9A-HJ-NP-Za-z]{21})) # base58 with underscore pad
18
+ ([-0-9A-Z_a-z])$/x.freeze # lax variant bookend and zero-width boundary
19
+
11
20
  ENCODE = {
12
21
  32 => -> (bin, align = true) {
13
22
  if align
@@ -18,7 +27,15 @@ module UUID::NCName
18
27
 
19
28
  out = ::Base32.encode bin
20
29
 
21
- out.downcase[0, 25]
30
+ out.downcase[0, 25] # clip off the padding
31
+ },
32
+ 58 => -> (bin, _) {
33
+ variant = bin[-1].ord >> 4
34
+ # note the bitcoin alphabet is the one used in draft-msporny-base58
35
+ out = ::Base58.binary_to_base58(bin.chop, :bitcoin)
36
+ # we need to pad base58 with underscores because it is variable length
37
+ out + (?_ * (21 - out.length)) +
38
+ encode_version(variant) # encode_version does variant too
22
39
  },
23
40
  64 => -> (bin, align = true) {
24
41
  if align
@@ -29,10 +46,11 @@ module UUID::NCName
29
46
 
30
47
  out = ::Base64.urlsafe_encode64 bin
31
48
 
32
- out[0, 21]
49
+ out[0, 21] # clip off the padding
33
50
  },
34
51
  }
35
52
 
53
+ # note the version symbol is already removed
36
54
  DECODE = {
37
55
  32 => -> (str, align = true) {
38
56
  str = str.upcase[0, 25] + 'A======'
@@ -41,6 +59,11 @@ module UUID::NCName
41
59
 
42
60
  out.pack 'C*'
43
61
  },
62
+ 58 => -> (str, _) {
63
+ variant = decode_version(str[-1]) << 4
64
+ str = str.chop.tr ?_, ''
65
+ ::Base58.base58_to_binary(str, :bitcoin) + variant.chr
66
+ },
44
67
  64 => -> (str, align = true) {
45
68
  str = str[0, 21] + 'A=='
46
69
  out = ::Base64.urlsafe_decode64(str).unpack 'C*'
@@ -116,7 +139,7 @@ module UUID::NCName
116
139
  ],
117
140
  ]
118
141
 
119
- def self.encode_version version, radix
142
+ def self.encode_version version, radix = 64
120
143
  offset = radix == 32 ? 97 : 65
121
144
  ((version & 15) + offset).chr
122
145
  end
@@ -170,7 +193,7 @@ module UUID::NCName
170
193
  # @param radix [32, 64] either the number 32 or the number 64.
171
194
  #
172
195
  # @param version [0, 1] An optional formatting version, where 0 is
173
- # the naïve original version and 1 moves the +variant+ nybble out
196
+ # the naïve original version and 1 moves the `variant` nybble out
174
197
  # to the end of the identifier. You will be warned for the time
175
198
  # being if you do not set this parameter explicitly. The default
176
199
  # version is 1.
@@ -182,15 +205,16 @@ module UUID::NCName
182
205
  # Base64, the overhang is only ever 4 bits. This means that when
183
206
  # the terminating character is aligned, it will always be in the
184
207
  # range of the letters A through P in (the RFC 3548/4648
185
- # representations of) both Base32 and Base64. When +version+ is 1
208
+ # representations of) both Base32 and Base64. When `version` is 1
186
209
  # and the terminating character is aligned, RFC4122-compliant UUIDs
187
- # will always terminate with +I+, +J+, +K+, or +L+. Defaults to
188
- # +true+.
210
+ # will always terminate with `I`, `J`, `K`, or `L`. Defaults to
211
+ # `true`.
189
212
  #
190
213
  # @return [String] The NCName-formatted UUID.
191
-
214
+ #
192
215
  def self.to_ncname uuid, radix: 64, version: nil, align: true
193
- raise 'Radix must be either 32 or 64' unless [32, 64].include? radix
216
+ raise 'Radix must be either 32, 58, or 64' unless
217
+ [32, 58, 64].include? radix
194
218
  raise 'UUID must be something stringable' if uuid.nil? or
195
219
  not uuid.respond_to? :to_s
196
220
  align = !!align # coerce to a boolean
@@ -233,12 +257,12 @@ module UUID::NCName
233
257
  # @param radix [nil, 32, 64] Optional radix; will use heuristic if omitted.
234
258
  #
235
259
  # @param format [:str, :hex, :b64, :bin] An optional formatting
236
- # parameter; defaults to +:str+, the canonical string representation.
260
+ # parameter; defaults to `:str`, the canonical string representation.
237
261
  #
238
262
  # @param version [0, 1] See ::to_ncname. Defaults to 1.
239
263
  #
240
264
  # @param align [nil, true, false] See ::to_ncname for details.
241
- # Setting this parameter to +nil+, the default, will cause the
265
+ # Setting this parameter to `nil`, the default, will cause the
242
266
  # decoder to detect the alignment state from the identifier.
243
267
  #
244
268
  # @param validate [false, true] Check that the ninth (the variant)
@@ -246,7 +270,7 @@ module UUID::NCName
246
270
  #
247
271
  # @return [String, nil] The corresponding UUID or nil if the input
248
272
  # is malformed.
249
-
273
+ #
250
274
  def self.from_ncname ncname,
251
275
  radix: nil, format: :str, version: nil, align: nil, validate: false
252
276
  raise 'Format must be symbol-able' unless format.respond_to? :to_sym
@@ -260,29 +284,25 @@ module UUID::NCName
260
284
  return unless ncname and ncname.respond_to? :to_s
261
285
 
262
286
  ncname = ncname.to_s.strip.gsub(/\s+/, '')
263
- match = /^([A-Za-z])([0-9A-Za-z_-]{21,})$/.match(ncname) or return
287
+ match = MATCH.match(ncname) or return
288
+ return if align and !/[A-Pa-p]$/.match? ncname # MATCH is lax
264
289
 
290
+ # determine the radix from the input
265
291
  if radix
266
- raise "Radix must be 32 or 64, not #{radix}" unless [32, 64].any? radix
267
- return unless { 32 => 26, 64 => 22 }[radix] == ncname.length
292
+ raise ArgumentError, "Radix must be 32, 58, or 64, not #{radix}" unless
293
+ [32, 58, 64].any? radix
294
+ return unless { 32 => 26, 58 => 23, 64 => 22 }[radix] == ncname.length
268
295
  else
269
- len = ncname.length
270
-
271
- if ncname =~ /[_-]/
272
- radix = 64
273
- elsif len >= 26
274
- radix = 32
275
- elsif len >= 22
276
- radix = 64
277
- else
278
- # uh will this ever get executed now that i put in that return?
279
- raise "Not sure what to do with an identifier of length #{len}."
280
- end
296
+ radix = { 26 => 32, 23 => 58, 22 => 64}[ncname.length] or
297
+ raise ArgumentError,
298
+ "Not sure what to do with an identifier of length #{ncname.length}."
281
299
  end
282
300
 
283
- uuidver, content = match.captures
301
+ # note MATCH separates the variant
302
+ uuidver, *content = match.captures
303
+ content = content.join
284
304
 
285
- align = !!(content =~ /[A-Pa-p]$/) if align.nil?
305
+ align = !!(/[A-Pa-p]$/.match? content) if align.nil?
286
306
  uuidver = decode_version uuidver
287
307
  content = DECODE[radix].call content, align
288
308
 
@@ -303,7 +323,7 @@ module UUID::NCName
303
323
  # @param align [true, false] See ::to_ncname.
304
324
  #
305
325
  # @return [String] The Base64-encoded NCName
306
-
326
+ #
307
327
  def self.to_ncname_64 uuid, version: nil, align: true
308
328
  to_ncname uuid, version: version, align: align
309
329
  end
@@ -320,11 +340,42 @@ module UUID::NCName
320
340
  #
321
341
  # @return [String, nil] The corresponding UUID or nil if the input
322
342
  # is malformed.
323
-
343
+ #
324
344
  def self.from_ncname_64 ncname, format: :str, version: nil, align: nil
325
345
  from_ncname ncname, radix: 64, format: format
326
346
  end
327
347
 
348
+ # Shorthand for conversion to the Base58 version
349
+ #
350
+ # @param uuid [#to_s] The UUID
351
+ #
352
+ # @param version [0, 1] See ::to_ncname.
353
+ #
354
+ # @param align [true, false] See ::to_ncname.
355
+ #
356
+ # @return [String] The Base58-encoded NCName
357
+ #
358
+ def self.to_ncname_58 uuid, version: nil, align: true
359
+ to_ncname uuid, radix: 58, version: version, align: align
360
+ end
361
+
362
+ # Shorthand for conversion from the Base58 version
363
+ #
364
+ # @param ncname [#to_s] The Base58 variant of the NCName-encoded UUID
365
+ #
366
+ # @param format [:str, :hex, :b64, :bin] The format
367
+ #
368
+ # @param version [0, 1] See ::to_ncname.
369
+ #
370
+ # @param align [true, false] See ::to_ncname.
371
+ #
372
+ # @return [String, nil] The corresponding UUID or nil if the input
373
+ # is malformed.
374
+ #
375
+ def self.from_ncname_58 ncname, format: :str, version: nil, align: nil
376
+ from_ncname ncname, radix: 58, format: format
377
+ end
378
+
328
379
  # Shorthand for conversion to the Base32 version
329
380
  #
330
381
  # @param uuid [#to_s] The UUID
@@ -334,7 +385,7 @@ module UUID::NCName
334
385
  # @param align [true, false] See ::to_ncname.
335
386
  #
336
387
  # @return [String] The Base32-encoded NCName
337
-
388
+ #
338
389
  def self.to_ncname_32 uuid, version: nil, align: true
339
390
  to_ncname uuid, radix: 32, version: version, align: align
340
391
  end
@@ -351,7 +402,7 @@ module UUID::NCName
351
402
  #
352
403
  # @return [String, nil] The corresponding UUID or nil if the input
353
404
  # is malformed.
354
-
405
+ #
355
406
  def self.from_ncname_32 ncname, format: :str, version: nil, align: nil
356
407
  from_ncname ncname, radix: 32, format: format
357
408
  end
@@ -360,10 +411,10 @@ module UUID::NCName
360
411
  # version. This method can positively identify a token as a UUID
361
412
  # NCName, but there is a small subset of UUIDs which will produce
362
413
  # tokens which are valid in both versions. The method returns
363
- # +false+ if the token is invalid, otherwise it returns +0+ or +1+
414
+ # `false` if the token is invalid, otherwise it returns `0` or `1`
364
415
  # for the guessed version.
365
416
  #
366
- # @note Version 1 tokens always end with +I+, +J+, +K+, or +L+ (with
417
+ # @note Version 1 tokens always end with `I`, `J`, `K`, or `L` (with
367
418
  # base32 being case-insensitive), so tokens that end in something
368
419
  # else will always be version 0.
369
420
  #
@@ -372,9 +423,10 @@ module UUID::NCName
372
423
  # @param strict [false, true]
373
424
  #
374
425
  # @return [false, 0, 1]
426
+ #
375
427
  def self.valid? token, strict: false
376
428
  token = token.to_s
377
- if /^[A-Pa-p](?:[0-9A-Za-z_-]{21}|[2-7A-Za-z]{25})$/.match token
429
+ if MATCH.match? token
378
430
  # false is definitely version zero but true is only maybe version 1
379
431
  version = /^(?:.{21}[I-L]|.{25}[I-Li-l])$/.match(token) ? 1 : 0
380
432
 
@@ -6,5 +6,5 @@ unless Module.const_defined? 'UUID'
6
6
  end
7
7
 
8
8
  module UUID::NCName
9
- VERSION = "0.2.6"
9
+ VERSION = "0.3.0"
10
10
  end
@@ -32,6 +32,7 @@ DESC
32
32
  # surprisingly do not need this
33
33
  # spec.add_runtime_dependency 'uuidtools', '~> 2.1.5'
34
34
  spec.add_runtime_dependency 'base32', '~> 0.3.2'
35
+ spec.add_runtime_dependency 'base58', '~> 0.2.3'
35
36
 
36
37
  spec.add_development_dependency 'bundler', '~> 2.1'
37
38
  spec.add_development_dependency 'rake', '~> 13.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uuid-ncname
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Taylor
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-28 00:00:00.000000000 Z
11
+ date: 2021-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base32
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.3.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: base58
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.3
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -81,6 +95,7 @@ files:
81
95
  - ".gitignore"
82
96
  - ".rspec"
83
97
  - ".travis.yml"
98
+ - ".yardopts"
84
99
  - Gemfile
85
100
  - LICENSE
86
101
  - README.md
@@ -95,7 +110,7 @@ homepage: https://github.com/doriantaylor/rb-uuid-ncname
95
110
  licenses:
96
111
  - Apache-2.0
97
112
  metadata: {}
98
- post_install_message:
113
+ post_install_message:
99
114
  rdoc_options: []
100
115
  require_paths:
101
116
  - lib
@@ -110,8 +125,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
125
  - !ruby/object:Gem::Version
111
126
  version: '0'
112
127
  requirements: []
113
- rubygems_version: 3.1.2
114
- signing_key:
128
+ rubygems_version: 3.1.4
129
+ signing_key:
115
130
  specification_version: 4
116
131
  summary: Format a UUID as a valid NCName.
117
132
  test_files: []