Module: Qt::VariantCodec

Defined in:
lib/qt/variant_codec.rb

Overview

Encodes/decodes Ruby values for QVariant bridge transport.

Constant Summary collapse

PREFIX =
'qtv:'
DIRECT_ENCODERS =
{
  Integer => ->(v) { ['int', v.to_s] },
  Float => ->(v) { ['float', v.to_s] },
  String => lambda { |v|
    if StringCodec.binary_bytes?(v)
      ['ba', base64_encode(v)]
    else
      ['str', base64_encode(StringCodec.to_qt_text(v))]
    end
  }
}.freeze
JSON_ENCODABLE_CLASSES =
[Array, Hash].freeze

Class Method Summary collapse

Class Method Details

.base64_decode(value) ⇒ Object



65
66
67
# File 'lib/qt/variant_codec.rb', line 65

def base64_decode(value)
  value.unpack1('m0')
end

.base64_encode(value) ⇒ Object



61
62
63
# File 'lib/qt/variant_codec.rb', line 61

def base64_encode(value)
  [value].pack('m0')
end

.decode(value) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/qt/variant_codec.rb', line 32

def decode(value)
  raw = value.to_s
  return raw unless raw.start_with?(PREFIX)
  return nil if raw == "#{PREFIX}nil"

  tag, payload = raw.delete_prefix(PREFIX).split(':', 2)
  return raw if tag.nil? || payload.nil?

  decode_typed_payload(tag, payload, raw)
rescue ArgumentError, JSON::ParserError
  raw
end

.decode_typed_payload(tag, payload, raw) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
# File 'lib/qt/variant_codec.rb', line 49

def decode_typed_payload(tag, payload, raw)
  case tag
  when 'bool' then payload == '1'
  when 'int' then Integer(payload, 10)
  when 'float' then Float(payload)
  when 'str' then StringCodec.from_qt_text(base64_decode(payload))
  when 'ba' then base64_decode(payload).b
  when 'json' then JSON.parse(StringCodec.from_qt_text(base64_decode(payload)))
  else raw
  end
end

.encode(value) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/qt/variant_codec.rb', line 24

def encode(value)
  return "#{PREFIX}nil" if value.nil?
  return encode_boolean(value) if [true, false].include?(value)

  tag, payload = encoded_tag_and_payload(value)
  "#{PREFIX}#{tag}:#{payload}"
end

.encode_boolean(value) ⇒ Object



45
46
47
# File 'lib/qt/variant_codec.rb', line 45

def encode_boolean(value)
  "#{PREFIX}bool:#{value ? 1 : 0}"
end

.encoded_tag_and_payload(value) ⇒ Object



69
70
71
72
73
74
75
76
# File 'lib/qt/variant_codec.rb', line 69

def encoded_tag_and_payload(value)
  direct = DIRECT_ENCODERS[value.class]
  return direct.call(value) if direct

  return ['json', base64_encode(JSON.generate(value))] if JSON_ENCODABLE_CLASSES.any? { |k| value.is_a?(k) }

  ['str', base64_encode(value.to_s)]
end