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

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

Overview

String codecs — mirrors @solana/codecs-strings.

Instance Method Summary collapse

Instance Method Details

#base58_codecObject



44
45
46
47
48
49
50
51
52
53
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 44

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



57
58
59
60
61
62
63
64
65
66
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 57

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



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 100

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



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 83

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



70
71
72
73
74
75
76
77
78
79
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 70

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



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/solana/ruby/kit/codecs/strings.rb', line 23

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