Module: Solace::Utils::Codecs

Defined in:
lib/solace/utils/codecs.rb

Class Method Summary collapse

Class Method Details

.base58_to_binary(string) ⇒ Object

Helper: Base58 Decoding

Decodes a Base58 string into a binary string

Args:

string (String): The Base58 encoded string

Returns:

String: The decoded binary string


162
163
164
# File 'lib/solace/utils/codecs.rb', line 162

def self.base58_to_binary(string)
  base58_to_bytes(string).pack('C*')
end

.base58_to_bytes(string) ⇒ Object

Helper: Base58 Decoding

Decodes a Base58 string into a sequence of bytes

Args:

string (String): The Base58 encoded string

Returns:

String: The decoded bytes


194
195
196
# File 'lib/solace/utils/codecs.rb', line 194

def self.base58_to_bytes(string)
  Base58.base58_to_binary(string, :bitcoin).bytes
end

.base64_to_bytestream(base64) ⇒ Object

Helper: IO Stream

Creates a StringIO from a base64 string.

Args:

base64 (String): The base64 string to decode

Returns:

StringIO: A StringIO object containing the decoded bytes


23
24
25
# File 'lib/solace/utils/codecs.rb', line 23

def self.base64_to_bytestream(base64)
  StringIO.new(Base64.decode64(base64))
end

.binary_to_base58(binary) ⇒ Object

Helper: Binary to Base58 Encoding

Encodes a sequence of bytes in Base58 format

Args:

bytes (String): The bytes to encode

Returns:

String: The Base58 encoded string


146
147
148
# File 'lib/solace/utils/codecs.rb', line 146

def self.binary_to_base58(binary)
  Base58.binary_to_base58(binary, :bitcoin)
end

.bytes_to_base58(bytes) ⇒ Object

Helper: Base58 Encoding

Encodes a sequence of bytes in Base58 format

Args:

bytes (String): The bytes to encode

Returns:

String: The Base58 encoded string


178
179
180
# File 'lib/solace/utils/codecs.rb', line 178

def self.bytes_to_base58(bytes)
  binary_to_base58(bytes.pack('C*'))
end

.decode_compact_u16(io) ⇒ Object

Helper: Compact-u16 Decoding (ShortVec)

Decodes a compact-u16 (ShortVec) value from an IO-like object. Reads bytes one at a time, accumulating the result until the MSB is 0.

Args:

io (IO or StringIO): The input to read bytes from.

Returns:

[Integer, Integer]: The decoded value and the number of bytes read.


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/solace/utils/codecs.rb', line 84

def self.decode_compact_u16(io)
  value = 0
  shift = 0
  bytes_read = 0
  loop do
    byte = io.read(1)
    raise EOFError, 'Unexpected end of input while decoding compact-u16' unless byte

    byte = byte.ord
    value |= (byte & 0x7F) << shift
    bytes_read += 1
    break if (byte & 0x80).zero?

    shift += 7
  end
  [value, bytes_read]
end

.decode_le_u64(io) ⇒ Object

Helper: Little-Endian u64 Decoding

Decodes a little-endian u64 value from a sequence of bytes

Args:

io (IO or StringIO): The input to read bytes from.

Returns:

Integer: The decoded u64 value


130
131
132
# File 'lib/solace/utils/codecs.rb', line 130

def self.decode_le_u64(io)
  io.read(8).unpack1('Q<')
end

.encode_compact_u16(n) ⇒ Object

Helper: Compact-u16 Encoding (ShortVec)

Encodes a u16 value in a compact form

Args:

n (Integer): The u16 value to encode

Returns:

String: The compactly encoded u16 value


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/solace/utils/codecs.rb', line 39

def self.encode_compact_u16(n)
  out = []
  loop do
    # In general, n >> 7 shifts the bits of n to the right by
    # 7 positions, effectively dividing n by 128 and discarding
    # the remainder (integer division). This is commonly used in
    # encoding schemes to process one "byte" (7 bits) at a time.
    if (n >> 7).zero?
      out << n
      break
    else
      # The expression out << ((n & 0x7F) | 0x80) is used in variable-length
      # integer encoding, such as the compact-u16 encoding.
      #
      # n & 0x7F:
      #   - 0x7F is 127 in decimal, or 0111 1111 in binary.
      #   - n & 0x7F masks out all but the lowest 7 bits of n. This extracts the least significant 7 bits of n.
      #
      # (n & 0x7F) | 0x80:
      #   - 0x80 is 128 in decimal, or 1000 0000 in binary.
      #   - | (bitwise OR) sets the highest bit (the 8th bit) to 1.
      #   - This is a signal that there are more bytes to come in the encoding (i.e., the value hasn't been fully encoded yet).
      #
      # out << ...:
      #   - This appends the resulting byte to the out array.
      out << ((n & 0x7F) | 0x80)
      n >>= 7
    end
  end
  out.pack('C*')
end

.encode_le_u64(n) ⇒ Object

Helper: Little-Endian u64 Encoding

Encodes a u64 value in little-endian format

Args:

n (Integer): The u64 value to encode

Returns:

String: The little-endian encoded u64 value


114
115
116
# File 'lib/solace/utils/codecs.rb', line 114

def self.encode_le_u64(n)
  [n].pack('Q<') # 64-bit little-endian
end

.valid_base58?(string) ⇒ Boolean

Helper: Base58 Validation

Checks if a string is a valid Base58 string

Args:

string (String): The string to check

Returns:

Boolean: True if the string is a valid Base58 string, false otherwise

Returns:

  • (Boolean)


210
211
212
213
214
215
216
217
# File 'lib/solace/utils/codecs.rb', line 210

def self.valid_base58?(string)
  return false if string.nil? || string.empty?

  Base58.decode(string)
  true
rescue StandardError => _e
  false
end