Class: Hypertube::Core::Protocol::CommandSerializer

Inherits:
Object
  • Object
show all
Defined in:
lib/hypertube-ruby-sdk/core/protocol/command_serializer.rb

Constant Summary collapse

EMPTY_CONNECTION_DATA =

Packed once and frozen, reused for every call that has no connection data (instead of allocating + packing a fresh Array on every serialize call).

[0, 0, 0, 0, 0, 0, 0].pack('C*').freeze

Class Method Summary collapse

Class Method Details

.serialize(root_command, connection_data = nil, runtime_version = 0) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/hypertube-ruby-sdk/core/protocol/command_serializer.rb', line 19

def self.serialize(root_command, connection_data = nil, runtime_version = 0)
  # Binary (ASCII-8BIT) buffer so that appending Integers (0..255) via `<<`
  # writes the raw byte instead of encoding it as a multi-byte character.
  buffer = String.new(encoding: Encoding::ASCII_8BIT, capacity: 256)

  buffer << root_command.runtime_name
  buffer << runtime_version

  if connection_data
    buffer << connection_data.serialize_connection_data.pack('C*')
  else
    buffer << EMPTY_CONNECTION_DATA
  end

  buffer << Hypertube::Utils::RuntimeNameHt::RUBY
  buffer << root_command.command_type

  # Payload (recursive) - primitives/headers are written straight into the
  # binary buffer, no per-item Array + pack('C*') round-trip.
  serialize_recursively(root_command, buffer)

  # Single conversion to Array<Integer> at the very end, since downstream
  # callers (FFI transmitter, WebSocket/HTTP2 clients) expect that shape.
  buffer.bytes
end

.serialize_recursively(command, buffer) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/hypertube-ruby-sdk/core/protocol/command_serializer.rb', line 47

def self.serialize_recursively(command, buffer)
  command.payload.each do |item|
    if item.is_a?(Hypertube::Utils::Command)
      Hypertube::Core::Protocol::TypeSerializer.write_command_header(buffer, item)
      serialize_recursively(item, buffer)
    elsif Hypertube::Utils::TypesHandler.primitive_or_none?(item)
      Hypertube::Core::Protocol::TypeSerializer.write_primitive(buffer, item)
    else
      cached_reference = Hypertube::Core::ReferenceCache::ReferencesCache.instance.cache_reference(item)
      ref_command = Hypertube::Utils::Command.new(Hypertube::Utils::RuntimeNameHt::RUBY, Hypertube::Utils::CommandType::REFERENCE, [cached_reference])
      Hypertube::Core::Protocol::TypeSerializer.write_command_header(buffer, ref_command)
      serialize_recursively(ref_command, buffer)
    end
  end
end