Class: Base58Id

Inherits:
Object
  • Object
show all
Defined in:
lib/base58_id.rb,
lib/base58_id/version.rb

Constant Summary collapse

ALPHABET_58 =

Based on Base64 URL-safe alphabet but with I, O, l, 0, -, _ removed.

%w[
  A B C D E F G H   J K L M N   P Q R S T U V W X Y Z
  a b c d e f g h i j k   m n o p q r s t u v w x y z
    1 2 3 4 5 6 7 8 9
].freeze
ALPHABET_58_INVERT =
ALPHABET_58.each_with_index.to_h
ALPHABET_58_CHARS =
ALPHABET_58.join
CARET_ALPHABET_58_CHARS =
"^#{ALPHABET_58_CHARS}".freeze
UUID_PATTERN =
/\A(0x)?[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\z/i
UUID_BYTES_FORMAT =
'%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x'
DEFAULT_RANDOM_RANGE =
(0..((2**63) - 1))
DEFAULT_RANDOM_DIGITS =
10
VERSION =
'1.2.0'

Class Method Summary collapse

Class Method Details

.base58_to_integer(base58) ⇒ Object

Raises:

  • (ArgumentError)


30
31
32
33
34
# File 'lib/base58_id.rb', line 30

def self.base58_to_integer(base58)
  raise ArgumentError, 'argument must be a valid Base58 String' unless valid_base58?(base58)

  base58.chars.reduce(0) { |integer, digit| (integer * 58) + ALPHABET_58_INVERT[digit] }
end

.base58_to_uuid(base58) ⇒ Object



42
43
44
# File 'lib/base58_id.rb', line 42

def self.base58_to_uuid(base58)
  integer_to_uuid(base58_to_integer(base58))
end

.integer_to_base58(integer) ⇒ Object

Raises:

  • (ArgumentError)


23
24
25
26
27
28
# File 'lib/base58_id.rb', line 23

def self.integer_to_base58(integer)
  raise ArgumentError, 'argument must be an Integer' unless integer.is_a?(Integer)
  raise ArgumentError, 'argument must be greater than or equal to zero' if integer.negative?

  integer.digits(58).reduce('') { |str, digit| ALPHABET_58[digit] + str }
end

.integer_to_uuid(integer) ⇒ Object

Raises:

  • (ArgumentError)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/base58_id.rb', line 52

def self.integer_to_uuid(integer)
  raise ArgumentError, 'argument must be an Integer' unless integer.is_a?(Integer)
  raise ArgumentError, 'argument must be greater than or equal to zero' if integer.negative?

  bytes_array = integer.digits(256)

  raise ArgumentError, 'argument size must not require more than 16 bytes' if bytes_array.size > 16

  while bytes_array.size < 16
    bytes_array.push(0)
  end

  UUID_BYTES_FORMAT % bytes_array.reverse
end

.rand(*args) ⇒ Object



85
86
87
# File 'lib/base58_id.rb', line 85

def self.rand(*args)
  random_number(*args)
end

.random_digits(n = nil) ⇒ Object

Raises:

  • (ArgumentError)


89
90
91
92
93
94
95
# File 'lib/base58_id.rb', line 89

def self.random_digits(n = nil)
  n = DEFAULT_RANDOM_DIGITS if n.nil?

  raise ArgumentError, 'argument must be an Integer' unless n.is_a?(Integer)

  n.times.reduce('') { |str, _| str + ALPHABET_58[SecureRandom.random_number(58)] }
end

.random_number(max_or_range = nil) ⇒ Object



79
80
81
82
83
# File 'lib/base58_id.rb', line 79

def self.random_number(max_or_range = nil)
  max_or_range = DEFAULT_RANDOM_RANGE if max_or_range.nil?

  integer_to_base58(SecureRandom.random_number(max_or_range))
end

.uuid_to_base58(uuid) ⇒ Object

Raises:

  • (ArgumentError)


36
37
38
39
40
# File 'lib/base58_id.rb', line 36

def self.uuid_to_base58(uuid)
  raise ArgumentError, 'argument must be a valid UUID String' unless valid_uuid?(uuid)

  integer_to_base58(uuid_to_integer(uuid))
end

.uuid_to_integer(uuid) ⇒ Object

Raises:

  • (ArgumentError)


46
47
48
49
50
# File 'lib/base58_id.rb', line 46

def self.uuid_to_integer(uuid)
  raise ArgumentError, 'argument must be a valid UUID String' unless valid_uuid?(uuid)

  uuid.delete('-').to_i(16)
end

.valid_base58?(value) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


67
68
69
70
71
# File 'lib/base58_id.rb', line 67

def self.valid_base58?(value)
  raise ArgumentError, 'argument must be a String' unless value.is_a?(String)

  value.count(CARET_ALPHABET_58_CHARS).zero?
end

.valid_uuid?(value) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


73
74
75
76
77
# File 'lib/base58_id.rb', line 73

def self.valid_uuid?(value)
  raise ArgumentError, 'argument must be a String' unless value.is_a?(String)

  value.match?(UUID_PATTERN)
end