uuid-ncname 0.2.1 → 0.2.6

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: 9e388102139409aff9de824bcff21d8a7793796425d781e896deb04ad1032fce
4
- data.tar.gz: 06ff6b9f8f141db4fc5d3458c814be989f315b9f2bb3c77dc9a2ee81ba7d7b0c
3
+ metadata.gz: f82febb1e1498f1d602bd2225b730b7e9128b7ea7b811472465001ae9925e83d
4
+ data.tar.gz: 8f403882f98f9509c074e3b53c1aebe58ff0b0adbe9f248baf4df9ded59b7b25
5
5
  SHA512:
6
- metadata.gz: 66abf5bf9d94bf70b268c5e0a96f99b7579903f6e3dc3c697afcfb99a64acc58da32a1340269d5f93e2a9cec1cdb0f261da21d2c94c94462d5487a80a2301b4b
7
- data.tar.gz: 00e7081505f5a836bf5073e0b7a489a3b3a0e2620f54cc7619224786b09019fc5b9af43448a35393b6679a1256d4729f0a3f174d50d6ecb85a383a56fa5832c1
6
+ metadata.gz: b0c1948dd81504cd7241f2a5ad78e50f661b4d9b0868402fd3e393760a5ddf6d30be82f39b51d700e0ded7681efa65134fb0e37ffa27f2108c238ccb8d2cbdfe
7
+ data.tar.gz: 2c86dfc2b5ee4b1c1be7c1e8343e844bfa9df0a94ebf20b487fd5988b53df4e138ae05e44d5134b00c4e1092140d24042c3e1c5d90ad9238a87fea65ab165f3c
data/.gitignore CHANGED
@@ -7,6 +7,7 @@ syntax: glob
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *.gem
10
11
 
11
12
  # rspec failure tracking
12
13
  .rspec_status
data/README.md CHANGED
@@ -83,14 +83,13 @@ variants.
83
83
 
84
84
  Since I have already released this gem prior to this format change, I
85
85
  have added a `:version` parameter to both `to_ncname` and
86
- `from_ncname`. The version currently defaults to `0`, the old one, but
87
- will issue a warning if not explicitly set. Later I will change the
88
- default to `1`, while keeping the warning, then later still, finally
89
- remove the warning with 1 as the default. This should ensure that any
90
- code written during the transition produces the correct results.
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.
91
90
 
92
91
  > Unless you have to support identifiers generated from version 0.1.3
93
- > or newer, you should be running these methods with `version: 1`.
92
+ > or older, you should be running these methods with `version: 1`.
94
93
 
95
94
  ## Rationale & Method
96
95
 
@@ -116,8 +116,9 @@ module UUID::NCName
116
116
  ],
117
117
  ]
118
118
 
119
- def self.encode_version version
120
- ((version & 15) + 65).chr
119
+ def self.encode_version version, radix
120
+ offset = radix == 32 ? 97 : 65
121
+ ((version & 15) + offset).chr
121
122
  end
122
123
 
123
124
  def self.decode_version version
@@ -127,7 +128,7 @@ module UUID::NCName
127
128
  def self.warn_version version
128
129
  if version.nil?
129
130
  warn 'Set an explicit :version to remove this warning. See documentation.'
130
- version = 0
131
+ version = 1
131
132
  end
132
133
 
133
134
  raise 'Version must be 0 or 1' unless [0, 1].include? version
@@ -137,6 +138,27 @@ module UUID::NCName
137
138
 
138
139
  public
139
140
 
141
+ # This error gets thrown when a UUID-NCName token can't be
142
+ # positively determined to be one version or the other.
143
+ class AmbiguousToken < ArgumentError
144
+
145
+ # @return [String] The ambiguous token
146
+ attr_reader :token
147
+ # @return [String] The UUID when decoded using version 0
148
+ attr_reader :v0
149
+ # @return [String] The UUID when decoded using version 1
150
+ attr_reader :v1
151
+
152
+ # @param token [#to_s] The token in question
153
+ # @param v0 [#to_s] UUID decoded with decoding scheme version 0
154
+ # @param v1 [#to_s] UUID decoded with decoding scheme version 1
155
+
156
+ def initialize token, v0: nil, v1: nil
157
+ @v0 = v0 || from_ncname(token, version: 0)
158
+ @v1 = v1 || from_ncname(token, version: 1)
159
+ end
160
+ end
161
+
140
162
  # Converts a UUID (or object that when converted to a string looks
141
163
  # like a UUID) to an NCName. By default it produces the Base64
142
164
  # variant.
@@ -148,10 +170,10 @@ module UUID::NCName
148
170
  # @param radix [32, 64] either the number 32 or the number 64.
149
171
  #
150
172
  # @param version [0, 1] An optional formatting version, where 0 is
151
- # the naïve original version and 1 moves the `variant` nybble out
152
- # to the end of the identifier. You will be warned if you do not
153
- # set this parameter explicitly. The default is currently 0, but
154
- # will change in the next version.
173
+ # the naïve original version and 1 moves the +variant+ nybble out
174
+ # to the end of the identifier. You will be warned for the time
175
+ # being if you do not set this parameter explicitly. The default
176
+ # version is 1.
155
177
  #
156
178
  # @param align [true, false] Optional directive to treat the
157
179
  # terminating character as aligned to the numerical base of the
@@ -160,9 +182,10 @@ module UUID::NCName
160
182
  # Base64, the overhang is only ever 4 bits. This means that when
161
183
  # the terminating character is aligned, it will always be in the
162
184
  # range of the letters A through P in (the RFC 3548/4648
163
- # representations of) both Base32 and Base64. When `version` is 1
185
+ # representations of) both Base32 and Base64. When +version+ is 1
164
186
  # and the terminating character is aligned, RFC4122-compliant UUIDs
165
- # will always terminate with I, J, K, or L. Defaults to `true`.
187
+ # will always terminate with +I+, +J+, +K+, or +L+. Defaults to
188
+ # +true+.
166
189
  #
167
190
  # @return [String] The NCName-formatted UUID.
168
191
 
@@ -170,7 +193,7 @@ module UUID::NCName
170
193
  raise 'Radix must be either 32 or 64' unless [32, 64].include? radix
171
194
  raise 'UUID must be something stringable' if uuid.nil? or
172
195
  not uuid.respond_to? :to_s
173
- raise 'Align must be true or false' unless [true, false].include? align
196
+ align = !!align # coerce to a boolean
174
197
 
175
198
  # XXX remove this when appropriate
176
199
  version = warn_version(version)
@@ -195,14 +218,14 @@ module UUID::NCName
195
218
  raise 'Binary representation of UUID is shorter than 16 bytes' if
196
219
  bin.length < 16
197
220
 
198
- uuidver, content = TRANSFORM[version][0].call bin[0, 16]
221
+ uuidver, content = TRANSFORM[version].first.call bin[0, 16]
199
222
 
200
- encode_version(uuidver) + ENCODE[radix].call(content, align)
223
+ encode_version(uuidver, radix) + ENCODE[radix].call(content, align)
201
224
  end
202
225
 
203
226
  # Converts an NCName-encoded UUID back to its canonical
204
227
  # representation. Will return nil if the input doesn't match the
205
- # radix (if supplied) or is otherwise malformed. doesn't match
228
+ # radix (if supplied) or is otherwise malformed.
206
229
  #
207
230
  # @param ncname [#to_s] an NCName-encoded UUID, either a
208
231
  # 22-character (Base64) variant, or a 26-character (Base32) variant.
@@ -210,19 +233,22 @@ module UUID::NCName
210
233
  # @param radix [nil, 32, 64] Optional radix; will use heuristic if omitted.
211
234
  #
212
235
  # @param format [:str, :hex, :b64, :bin] An optional formatting
213
- # parameter; defaults to `:str`, the canonical string representation.
236
+ # parameter; defaults to +:str+, the canonical string representation.
214
237
  #
215
- # @param version [0, 1] See `to_ncname`. Defaults (for now) to 0.
238
+ # @param version [0, 1] See ::to_ncname. Defaults to 1.
216
239
  #
217
- # @param align [true, false, nil] See `to_ncname` for details.
218
- # Setting this parameter to `nil`, the default, will cause the
240
+ # @param align [nil, true, false] See ::to_ncname for details.
241
+ # Setting this parameter to +nil+, the default, will cause the
219
242
  # decoder to detect the alignment state from the identifier.
220
243
  #
244
+ # @param validate [false, true] Check that the ninth (the variant)
245
+ # octet is correctly masked _after_ decoding.
246
+ #
221
247
  # @return [String, nil] The corresponding UUID or nil if the input
222
248
  # is malformed.
223
249
 
224
250
  def self.from_ncname ncname,
225
- radix: nil, format: :str, version: nil, align: nil
251
+ radix: nil, format: :str, version: nil, align: nil, validate: false
226
252
  raise 'Format must be symbol-able' unless format.respond_to? :to_sym
227
253
  raise "Invalid format #{format}" unless FORMAT[format]
228
254
  raise 'Align must be true, false, or nil' unless
@@ -262,6 +288,9 @@ module UUID::NCName
262
288
 
263
289
  bin = TRANSFORM[version][1].call uuidver, content
264
290
 
291
+ # double-check the variant (high-order bits have to be 10)
292
+ return if validate and bin[8].ord >> 6 != 2
293
+
265
294
  FORMAT[format].call bin
266
295
  end
267
296
 
@@ -269,9 +298,9 @@ module UUID::NCName
269
298
  #
270
299
  # @param uuid [#to_s] The UUID
271
300
  #
272
- # @param version [0, 1] See `to_ncname`.
301
+ # @param version [0, 1] See ::to_ncname.
273
302
  #
274
- # @param align [true, false] See `to_ncname`.
303
+ # @param align [true, false] See ::to_ncname.
275
304
  #
276
305
  # @return [String] The Base64-encoded NCName
277
306
 
@@ -285,9 +314,9 @@ module UUID::NCName
285
314
  #
286
315
  # @param format [:str, :hex, :b64, :bin] The format
287
316
  #
288
- # @param version [0, 1] See `to_ncname`.
317
+ # @param version [0, 1] See ::to_ncname.
289
318
  #
290
- # @param align [true, false] See `to_ncname`.
319
+ # @param align [true, false] See ::to_ncname.
291
320
  #
292
321
  # @return [String, nil] The corresponding UUID or nil if the input
293
322
  # is malformed.
@@ -300,9 +329,9 @@ module UUID::NCName
300
329
  #
301
330
  # @param uuid [#to_s] The UUID
302
331
  #
303
- # @param version [0, 1] See `to_ncname`.
332
+ # @param version [0, 1] See ::to_ncname.
304
333
  #
305
- # @param align [true, false] See `to_ncname`.
334
+ # @param align [true, false] See ::to_ncname.
306
335
  #
307
336
  # @return [String] The Base32-encoded NCName
308
337
 
@@ -316,9 +345,9 @@ module UUID::NCName
316
345
  #
317
346
  # @param format [:str, :hex, :b64, :bin] The format
318
347
  #
319
- # @param version [0, 1] See `to_ncname`.
348
+ # @param version [0, 1] See ::to_ncname.
320
349
  #
321
- # @param align [true, false] See `to_ncname`.
350
+ # @param align [true, false] See ::to_ncname.
322
351
  #
323
352
  # @return [String, nil] The corresponding UUID or nil if the input
324
353
  # is malformed.
@@ -327,4 +356,46 @@ module UUID::NCName
327
356
  from_ncname ncname, radix: 32, format: format
328
357
  end
329
358
 
359
+ # Test if the given token is a UUID NCName, with a hint to its
360
+ # version. This method can positively identify a token as a UUID
361
+ # NCName, but there is a small subset of UUIDs which will produce
362
+ # tokens which are valid in both versions. The method returns
363
+ # +false+ if the token is invalid, otherwise it returns +0+ or +1+
364
+ # for the guessed version.
365
+ #
366
+ # @note Version 1 tokens always end with +I+, +J+, +K+, or +L+ (with
367
+ # base32 being case-insensitive), so tokens that end in something
368
+ # else will always be version 0.
369
+ #
370
+ # @param token [#to_s] The token to test
371
+ #
372
+ # @param strict [false, true]
373
+ #
374
+ # @return [false, 0, 1]
375
+ def self.valid? token, strict: false
376
+ token = token.to_s
377
+ if /^[A-Pa-p](?:[0-9A-Za-z_-]{21}|[2-7A-Za-z]{25})$/.match token
378
+ # false is definitely version zero but true is only maybe version 1
379
+ version = /^(?:.{21}[I-L]|.{25}[I-Li-l])$/.match(token) ? 1 : 0
380
+
381
+ # try decoding with validation on
382
+ uu = from_ncname token, version: version, validate: true
383
+
384
+ # note that version 1 will always return something because the
385
+ # method of detecting it is a version 1 also happens to be the
386
+ # method of determining whether or not it is valid.
387
+ return false unless uu
388
+
389
+ if version == 1 and strict
390
+ # but we can also check if the input is a valid version 0
391
+ u0 = from_ncname token, version: 0, validate: true
392
+ raise AmbiguousToken.new(token, v0: u0, v1: uu) if u0
393
+ end
394
+
395
+ version
396
+ else
397
+ false
398
+ end
399
+ end
400
+
330
401
  end
@@ -1,7 +1,10 @@
1
+ # this is here because it reasonable to expect a *class* in the
2
+ # namespace called UUID, so if you say `module UUID; module NCName`,
3
+ # it will croak with a "TypeError: UUID is not a module".
1
4
  unless Module.const_defined? 'UUID'
2
5
  module UUID; end
3
6
  end
4
7
 
5
8
  module UUID::NCName
6
- VERSION = "0.2.1"
9
+ VERSION = "0.2.6"
7
10
  end
@@ -33,9 +33,9 @@ DESC
33
33
  # spec.add_runtime_dependency 'uuidtools', '~> 2.1.5'
34
34
  spec.add_runtime_dependency 'base32', '~> 0.3.2'
35
35
 
36
- spec.add_development_dependency 'bundler', '~> 1.16'
37
- spec.add_development_dependency 'rake', '~> 10.0'
38
- spec.add_development_dependency 'rspec', '~> 3.0'
36
+ spec.add_development_dependency 'bundler', '~> 2.1'
37
+ spec.add_development_dependency 'rake', '~> 13.0'
38
+ spec.add_development_dependency 'rspec', '~> 3.9'
39
39
 
40
40
  # only need it for testing, who knew
41
41
  # spec.add_development_dependency 'uuidtools', '~> 2.1.5'
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.1
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Taylor
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-25 00:00:00.000000000 Z
11
+ date: 2020-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base32
@@ -30,42 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.16'
33
+ version: '2.1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.16'
40
+ version: '2.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.0'
61
+ version: '3.9'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.0'
68
+ version: '3.9'
69
69
  description: |
70
70
  This module creates an isomorphic representation of a UUID which is
71
71
  guaranteed to fit into the grammar of the XML NCName construct, which
@@ -110,8 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
112
  requirements: []
113
- rubyforge_project:
114
- rubygems_version: 2.7.6
113
+ rubygems_version: 3.1.2
115
114
  signing_key:
116
115
  specification_version: 4
117
116
  summary: Format a UUID as a valid NCName.