lib/uuid/ncname.rb in uuid-ncname-0.2.3 vs lib/uuid/ncname.rb in uuid-ncname-0.2.4
- old
+ new
@@ -125,11 +125,11 @@
end
def self.warn_version version
if version.nil?
warn 'Set an explicit :version to remove this warning. See documentation.'
- version = 0
+ version = 1
end
raise 'Version must be 0 or 1' unless [0, 1].include? version
version
@@ -147,13 +147,13 @@
#
# @param radix [32, 64] either the number 32 or the number 64.
#
# @param version [0, 1] An optional formatting version, where 0 is
# the naïve original version and 1 moves the `variant` nybble out
- # to the end of the identifier. You will be warned if you do not
- # set this parameter explicitly. The default is currently 0, but
- # will change in the next version.
+ # to the end of the identifier. You will be warned for the time
+ # being if you do not set this parameter explicitly. The default
+ # version is 1.
#
# @param align [true, false] Optional directive to treat the
# terminating character as aligned to the numerical base of the
# representation. Since the version nybble is removed from the
# string and the first 120 bits divide evenly into both Base32 and
@@ -200,31 +200,34 @@
encode_version(uuidver) + ENCODE[radix].call(content, align)
end
# Converts an NCName-encoded UUID back to its canonical
# representation. Will return nil if the input doesn't match the
- # radix (if supplied) or is otherwise malformed. doesn't match
+ # radix (if supplied) or is otherwise malformed.
#
# @param ncname [#to_s] an NCName-encoded UUID, either a
# 22-character (Base64) variant, or a 26-character (Base32) variant.
#
# @param radix [nil, 32, 64] Optional radix; will use heuristic if omitted.
#
# @param format [:str, :hex, :b64, :bin] An optional formatting
# parameter; defaults to `:str`, the canonical string representation.
#
- # @param version [0, 1] See `to_ncname`. Defaults (for now) to 0.
+ # @param version [0, 1] See #to_ncname. Defaults to 1.
#
- # @param align [true, false, nil] See `to_ncname` for details.
+ # @param align [nil, true, false] See #to_ncname for details.
# Setting this parameter to `nil`, the default, will cause the
# decoder to detect the alignment state from the identifier.
#
+ # @param validate [false, true] Check that the ninth octet is
+ # correctly masked _after_ decoding.
+ #
# @return [String, nil] The corresponding UUID or nil if the input
# is malformed.
def self.from_ncname ncname,
- radix: nil, format: :str, version: nil, align: nil
+ radix: nil, format: :str, version: nil, align: nil, validate: false
raise 'Format must be symbol-able' unless format.respond_to? :to_sym
raise "Invalid format #{format}" unless FORMAT[format]
raise 'Align must be true, false, or nil' unless
[true, false, nil].include? align
@@ -260,20 +263,23 @@
uuidver = decode_version uuidver
content = DECODE[radix].call content, align
bin = TRANSFORM[version][1].call uuidver, content
+ # double-check the variant (high-order bits have to be 10)
+ return if validate and bin[8].ord >> 6 != 2
+
FORMAT[format].call bin
end
# Shorthand for conversion to the Base64 version
#
# @param uuid [#to_s] The UUID
#
- # @param version [0, 1] See `to_ncname`.
+ # @param version [0, 1] See #to_ncname.
#
- # @param align [true, false] See `to_ncname`.
+ # @param align [true, false] See #to_ncname.
#
# @return [String] The Base64-encoded NCName
def self.to_ncname_64 uuid, version: nil, align: true
to_ncname uuid, version: version, align: align
@@ -283,13 +289,13 @@
#
# @param ncname [#to_s] The Base64 variant of the NCName-encoded UUID
#
# @param format [:str, :hex, :b64, :bin] The format
#
- # @param version [0, 1] See `to_ncname`.
+ # @param version [0, 1] See #to_ncname.
#
- # @param align [true, false] See `to_ncname`.
+ # @param align [true, false] See #to_ncname.
#
# @return [String, nil] The corresponding UUID or nil if the input
# is malformed.
def self.from_ncname_64 ncname, format: :str, version: nil, align: nil
@@ -298,13 +304,13 @@
# Shorthand for conversion to the Base32 version
#
# @param uuid [#to_s] The UUID
#
- # @param version [0, 1] See `to_ncname`.
+ # @param version [0, 1] See #to_ncname.
#
- # @param align [true, false] See `to_ncname`.
+ # @param align [true, false] See #to_ncname.
#
# @return [String] The Base32-encoded NCName
def self.to_ncname_32 uuid, version: nil, align: true
to_ncname uuid, radix: 32, version: version, align: align
@@ -314,35 +320,48 @@
#
# @param ncname [#to_s] The Base32 variant of the NCName-encoded UUID
#
# @param format [:str, :hex, :b64, :bin] The format
#
- # @param version [0, 1] See `to_ncname`.
+ # @param version [0, 1] See #to_ncname.
#
- # @param align [true, false] See `to_ncname`.
+ # @param align [true, false] See #to_ncname.
#
# @return [String, nil] The corresponding UUID or nil if the input
# is malformed.
def self.from_ncname_32 ncname, format: :str, version: nil, align: nil
from_ncname ncname, radix: 32, format: format
end
- # Test if the given token is a UUID NCName, with a hint to its version.
+ # Test if the given token is a UUID NCName, with a hint to its
+ # version. This method can positively identify a token as a UUID
+ # NCName, but there is a small subset of UUIDs which will produce
+ # tokens which are valid in both versions. The method returns
+ # `false` if the token is invalid, otherwise it returns `0` or `1`
+ # for the guessed version.
#
+ # @note Version 1 tokens always end with I, J, K, or L (with base32
+ # being case-insensitive), so tokens that end in something else will
+ # be version 0.
+ #
# @param token [#to_s] The token to test
#
# @return [false, 0, 1]
def self.valid? token
token = token.to_s
- if /^[A-P](?:[0-9A-Za-z_-]{21}|[2-7A-Za-z]{25})$/.match token
+ if /^[A-Pa-p](?:[0-9A-Za-z_-]{21}|[2-7A-Za-z]{25})$/.match token
# false is definitely version zero but true is only maybe version 1
- version = /[IJKLijkl]$/.match(token) ? 1 : 0
+ version = /^(?:.{21}[I-L]|.{25}[I-Li-l])$/.match(token) ? 1 : 0
- if version == 1
- uu = from_ncname token, version: 1
- # lol even this isn't a guarantee
- /[89ab]/.match(uu[19]) ? 1 : version
+ # try decoding with validation on
+ uu = from_ncname token, version: version, validate: true
+
+ if version == 1 and !uu
+ # try version zero
+ uu = from_ncname token, version: 0, validate: true
+ # either zero or invalid
+ uu ? 0 : false
else
version
end
else
false