Module: Solana::Ruby::Kit::Codecs::Strings

Extended by:
T::Sig
Included in:
Solana::Ruby::Kit::Codecs
Defined in:
lib/solana/ruby/kit/codecs/strings.rb

Overview

String codecs — mirrors @solana/codecs-strings.

Class Method Summary collapse

Class Method Details

.base58_codecObject



40
41
42
43
44
45
46
47
48
49
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 40

def base58_codec
  enc = Encoder.new do |v|
    Solana::Ruby::Kit::Encoding::Base58.decode(v.to_s)
  end
  dec = Decoder.new do |bytes, offset|
    remaining = bytes.b.byteslice(offset..) || ''.b
    [Solana::Ruby::Kit::Encoding::Base58.encode(remaining), remaining.bytesize]
  end
  Codec.new(enc, dec)
end

.base64_codecObject



53
54
55
56
57
58
59
60
61
62
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 53

def base64_codec
  enc = Encoder.new do |v|
    Base64.strict_encode64(v.to_s)
  end
  dec = Decoder.new do |bytes, offset|
    remaining = bytes.b.byteslice(offset..) || ''.b
    [Base64.strict_decode64(remaining.force_encoding('ASCII')), remaining.bytesize]
  end
  Codec.new(enc, dec)
end

.bit_array_codec(size) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 96

def bit_array_codec(size)
  total_bits = size * 8
  enc = Encoder.new(fixed_size: size) do |bits|
    arr   = T.cast(bits, T::Array[T::Boolean])
    bytes = Array.new(size, 0)
    arr.first(total_bits).each_with_index do |bit, idx|
      bytes[idx / 8] |= (1 << (idx % 8)) if bit
    end
    bytes.pack('C*')
  end
  dec = Decoder.new(fixed_size: size) do |bytes, offset|
    slice = bytes.b.byteslice(offset, size) || ''.b
    byte_arr = T.cast(T.unsafe(slice).unpack('C*'), T::Array[Integer])
    bits = byte_arr.flat_map { |byte| 8.times.map { |i| byte[i] == 1 } }
    [bits, size]
  end
  Codec.new(enc, dec)
end

.bytes_codec(size) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 79

def bytes_codec(size)
  enc = Encoder.new(fixed_size: size) do |v|
    b = v.is_a?(String) ? v.b : v.to_s.b
    Kernel.raise ArgumentError, "Expected #{size} bytes, got #{b.bytesize}" if b.bytesize != size

    b
  end
  dec = Decoder.new(fixed_size: size) do |bytes, offset|
    slice = bytes.b.byteslice(offset, size) || ''.b
    [slice, size]
  end
  Codec.new(enc, dec)
end

.hex_codecObject



66
67
68
69
70
71
72
73
74
75
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 66

def hex_codec
  enc = Encoder.new do |v|
    [v.to_s.tr(' ', '')].pack('H*')
  end
  dec = Decoder.new do |bytes, offset|
    remaining = bytes.b.byteslice(offset..) || ''.b
    [remaining.unpack1('H*'), remaining.bytesize]
  end
  Codec.new(enc, dec)
end

.utf8_codec(size: nil) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 19

def utf8_codec(size: nil)
  enc = Encoder.new(fixed_size: size) do |v|
    raw = v.to_s.encode('UTF-8').b
    if size
      raw.bytesize <= size ? raw.ljust(size, "\x00") : raw.byteslice(0, size) || ''.b
    else
      raw
    end
  end
  dec = Decoder.new(fixed_size: size) do |bytes, offset|
    len   = size || (bytes.bytesize - offset)
    slice = bytes.b.byteslice(offset, len) || ''.b
    # Strip null padding for fixed-size strings
    str   = size ? slice.delete_suffix("\x00" * slice.bytesize.times.take_while { |i| slice.b[-1 - i] == "\x00" }.length) : slice
    [str.force_encoding('UTF-8'), len]
  end
  Codec.new(enc, dec)
end