module KSUID::Base62

Converts between numbers and an alphanumeric encoding

We store and report KSUIDs as base 62-encoded numbers to make them lexicographically sortable and compact to transmit. The base 62 alphabet consists of the Arabic numerals, followed by the English capital letters and the English lowercase letters.

Constants

BASE

The base (62) that this module encodes numbers into

@api private

CHARSET

The character set used to encode numbers into base 62

@api private

Public Class Methods

compatible?(string) click to toggle source

Checks whether a string is a base 62-compatible string

@api public

@example Checks a KSUID for base 62 compatibility

KSUID::Base62.compatible?("15Ew2nYeRDscBipuJicYjl970D1") #=> true

@param string [String] the string to check for compatibility @return [Boolean]

# File lib/ksuid/base62.rb, line 32
def self.compatible?(string)
  string.each_char.all? { |char| CHARSET.include?(char) }
end
decode(ksuid) click to toggle source

Decodes a base 62-encoded string into an integer

@api public

@example Decode a string into a number

KSUID::Base62.decode('0000000000000000000001LY7VK')
#=> 1234567890

@param ksuid [String] the base 62-encoded number @return [Integer] the decoded number as an integer

# File lib/ksuid/base62.rb, line 46
def self.decode(ksuid)
  result = 0

  ksuid.split('').each_with_index do |char, position|
    unless (digit = CHARSET.index(char))
      raise(ArgumentError, "#{ksuid} is not a base 62 number")
    end

    result += digit * BASE**(ksuid.length - (position + 1))
  end

  result
end
encode(number) click to toggle source

Encodes a number (integer) as a base 62 string

@api public

@example Encode a number as a base 62 string

KSUID::Base62.encode(1_234_567_890)
#=> "0000000000000000000001LY7VK"

@param number [Integer] the number to encode into base 62 @return [String] the base 62-encoded number

# File lib/ksuid/base62.rb, line 70
def self.encode(number)
  chars = encode_without_padding(number)

  chars << padding if chars.empty?
  chars.reverse.join('').rjust(STRING_LENGTH, padding)
end
encode_bytes(bytes) click to toggle source

Encodes a byte string or byte array into base 62

@api semipublic

@example Encode a maximal KSUID as a string

KSUID::Base62.encode_bytes(
  [255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
   255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
)

@param bytes [String, Array<Integer>] the bytes to encode @return [String] the encoded bytes as a base 62 string

# File lib/ksuid/base62.rb, line 89
def self.encode_bytes(bytes)
  encode(Utils.int_from_bytes(bytes))
end

Private Class Methods

encode_without_padding(number) click to toggle source

Encodes a number as a string while disregarding the expected width

@api private

@param number [Integer] the number to encode @return [String] the resulting encoded string

# File lib/ksuid/base62.rb, line 99
def self.encode_without_padding(number)
  [].tap do |chars|
    loop do
      break unless number.positive?

      number, remainder = number.divmod(BASE)
      chars << CHARSET[remainder]
    end
  end
end
padding() click to toggle source

The character used as padding in strings that are less than 27 characters

@api private @return [String]

# File lib/ksuid/base62.rb, line 115
def self.padding
  CHARSET[0]
end