Module: Plushie::Protocol::Encode
- Defined in:
- lib/plushie/protocol/encode.rb
Overview
Outbound message encoding for the wire protocol.
Every method produces wire-ready bytes (iodata for msgpack, JSONL string for json). The session field defaults to "" and is injected by the Connection or SessionPool when multiplexing.
Class Method Summary collapse
-
.encode(map, format = :msgpack) ⇒ String
Encode an arbitrary hash as wire-format bytes.
-
.encode_advance_frame(timestamp, format = :msgpack) ⇒ String
Advance the animation clock by one frame.
-
.encode_binary(data, format) ⇒ String
Encode binary data for the wire format.
-
.encode_binary_field(payload, key, format) ⇒ Hash
Encode a binary field in a payload hash if present.
-
.encode_command(id, family, value = nil, format = :msgpack) ⇒ String
Send a command to a widget by ID.
-
.encode_commands(commands, format = :msgpack) ⇒ String
Send multiple widget-targeted commands in a single message.
-
.encode_effect(id, kind, payload, format = :msgpack) ⇒ String
Request a platform effect (file dialog, clipboard, notification).
-
.encode_image_op(op, payload, format = :msgpack) ⇒ String
Manage in-memory image handles (create, update, delete, list, clear).
-
.encode_interact(id, action, selector = nil, payload = {}, format = :msgpack) ⇒ String
Simulate a user interaction (click, type, toggle, etc.).
-
.encode_load_font(family, data, format = :msgpack) ⇒ String
Encode a typed +load_font+ message.
-
.encode_patch(ops, format = :msgpack) ⇒ String
Incrementally patch the existing tree.
-
.encode_query(id, target, selector = {}, format = :msgpack) ⇒ String
Query the renderer's tree (find widget, get full tree).
-
.encode_register_effect_stub(kind, response, format = :msgpack) ⇒ String
Register an effect stub with the renderer.
-
.encode_reset(id, format = :msgpack) ⇒ String
Reset all session state.
-
.encode_screenshot(id, name, width = 1024, height = 768, format = :msgpack) ⇒ String
Capture rendered pixels.
-
.encode_settings(settings, format = :msgpack) ⇒ String
Encode application-level settings.
-
.encode_snapshot(tree, format = :msgpack) ⇒ String
Replace the entire UI tree.
-
.encode_subscribe(kind, tag, format = :msgpack, max_rate: nil, window_id: nil) ⇒ String
Subscribe to an event category.
-
.encode_system_op(op, payload, format = :msgpack) ⇒ String
Send a system-level operation not tied to a specific window.
-
.encode_system_query(op, payload, format = :msgpack) ⇒ String
Send a system-level query.
-
.encode_tree_hash(id, name, format = :msgpack) ⇒ String
Compute a SHA-256 hash of the renderer's current tree.
-
.encode_unregister_effect_stub(kind, format = :msgpack) ⇒ String
Remove a previously registered effect stub.
-
.encode_unsubscribe(kind, tag: nil, format: :msgpack) ⇒ String
Unsubscribe from an event category.
-
.encode_widget_op(op, payload, format = :msgpack) ⇒ String
Perform an operation on a widget (focus, scroll, etc.).
-
.encode_window_op(op, window_id, payload, format = :msgpack) ⇒ String
Manage a window (open, close, resize, etc.).
-
.normalize_default_font(settings) ⇒ Object
private
The renderer reads +default_font+ strictly as an object with at least a +family+ key; a bare string is silently dropped and the renderer falls back to the platform default.
-
.stringify_keys(obj) ⇒ Object
Recursively convert all symbol keys to strings.
Class Method Details
.encode(map, format = :msgpack) ⇒ String
Encode an arbitrary hash as wire-format bytes.
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/plushie/protocol/encode.rb', line 23 def encode(map, format = :msgpack) case format when :json JSON.generate(stringify_keys(map)) + "\n" when :msgpack require "msgpack" MessagePack.pack(stringify_keys(map)) else raise ArgumentError, "unknown format: #{format.inspect}" end end |
.encode_advance_frame(timestamp, format = :msgpack) ⇒ String
Advance the animation clock by one frame.
385 386 387 |
# File 'lib/plushie/protocol/encode.rb', line 385 def encode_advance_frame(, format = :msgpack) encode({type: "advance_frame", session: "", timestamp: }, format) end |
.encode_binary(data, format) ⇒ String
Encode binary data for the wire format. JSON: base64-encoded string. MessagePack: raw binary pass-through.
439 440 441 442 443 444 |
# File 'lib/plushie/protocol/encode.rb', line 439 def encode_binary(data, format) case format when :json then Base64.strict_encode64(data) when :msgpack then data end end |
.encode_binary_field(payload, key, format) ⇒ Hash
Encode a binary field in a payload hash if present. Returns a new hash with the field encoded for the wire format, or the original hash if the field is absent or nil.
454 455 456 457 |
# File 'lib/plushie/protocol/encode.rb', line 454 def encode_binary_field(payload, key, format) return payload unless payload.is_a?(Hash) && payload.key?(key) && payload[key].is_a?(String) payload.merge(key => encode_binary(payload[key], format)) end |
.encode_command(id, family, value = nil, format = :msgpack) ⇒ String
Send a command to a widget by ID.
Uses the unified wire format matching events: "command", id: "widget_id", family: "op_name", value: ...
274 275 276 277 278 279 |
# File 'lib/plushie/protocol/encode.rb', line 274 def encode_command(id, family, value = nil, format = :msgpack) encode({ type: "command", session: "", id: id, family: family.to_s, value: value }, format) end |
.encode_commands(commands, format = :msgpack) ⇒ String
Send multiple widget-targeted commands in a single message.
286 287 288 289 290 291 292 293 |
# File 'lib/plushie/protocol/encode.rb', line 286 def encode_commands(commands, format = :msgpack) encode({ type: "commands", session: "", commands: commands.map { |c| {id: c[:id], family: c[:family].to_s, value: c[:value]} } }, format) end |
.encode_effect(id, kind, payload, format = :msgpack) ⇒ String
Request a platform effect (file dialog, clipboard, notification).
214 215 216 217 218 219 |
# File 'lib/plushie/protocol/encode.rb', line 214 def encode_effect(id, kind, payload, format = :msgpack) encode({ type: "effect", session: "", id: id, kind: kind.to_s, payload: payload }, format) end |
.encode_image_op(op, payload, format = :msgpack) ⇒ String
Manage in-memory image handles (create, update, delete, list, clear).
Uses the unified +_op+ envelope: op-specific data lives under +payload+. Binary fields (data, pixels) are base64-encoded for JSON and passed as raw binary for MessagePack.
Field set per op:
- +create_image+/+update_image+: +handle+, plus +data+ or (+pixels+, +width+, +height+).
- +delete_image+: +handle+.
- +list+: +tag+ (response routes through op_query_response).
- +clear+: empty payload.
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/plushie/protocol/encode.rb', line 242 def encode_image_op(op, payload, format = :msgpack) op_payload = {} op_payload[:handle] = payload[:handle] if payload[:handle] op_payload[:tag] = payload[:tag].to_s if payload[:tag] if payload[:data] op_payload[:data] = encode_binary(payload[:data], format) end if payload[:pixels] op_payload[:pixels] = encode_binary(payload[:pixels], format) op_payload[:width] = payload[:width] op_payload[:height] = payload[:height] end encode({type: "image_op", session: "", op: op.to_s, payload: op_payload}, format) end |
.encode_interact(id, action, selector = nil, payload = {}, format = :msgpack) ⇒ String
Simulate a user interaction (click, type, toggle, etc.).
325 326 327 328 329 330 331 332 |
# File 'lib/plushie/protocol/encode.rb', line 325 def encode_interact(id, action, selector = nil, payload = {}, format = :msgpack) msg = { type: "interact", session: "", id: id, action: action.to_s, payload: payload } msg[:selector] = selector if selector encode(msg, format) end |
.encode_load_font(family, data, format = :msgpack) ⇒ String
Encode a typed +load_font+ message.
Wire shape: +type = "load_font"+ with +payload = data+. JSON framing emits +data+ as a base64 string; MessagePack framing emits +data+ as a native binary value.
147 148 149 150 |
# File 'lib/plushie/protocol/encode.rb', line 147 def encode_load_font(family, data, format = :msgpack) payload = encode_binary_field({family: family, data: data}, :data, format) encode({type: "load_font", session: "", payload: payload}, format) end |
.encode_patch(ops, format = :msgpack) ⇒ String
Incrementally patch the existing tree.
89 90 91 |
# File 'lib/plushie/protocol/encode.rb', line 89 def encode_patch(ops, format = :msgpack) encode({type: "patch", session: "", ops: ops}, format) end |
.encode_query(id, target, selector = {}, format = :msgpack) ⇒ String
Query the renderer's tree (find widget, get full tree).
306 307 308 309 310 311 |
# File 'lib/plushie/protocol/encode.rb', line 306 def encode_query(id, target, selector = {}, format = :msgpack) encode({ type: "query", session: "", id: id, target: target, selector: selector }, format) end |
.encode_register_effect_stub(kind, response, format = :msgpack) ⇒ String
Register an effect stub with the renderer. The renderer will return the given response immediately for any effect of the given kind, without executing the real effect.
401 402 403 |
# File 'lib/plushie/protocol/encode.rb', line 401 def encode_register_effect_stub(kind, response, format = :msgpack) encode({type: "register_effect_stub", session: "", kind: kind.to_s, response: response}, format) end |
.encode_reset(id, format = :msgpack) ⇒ String
Reset all session state.
372 373 374 |
# File 'lib/plushie/protocol/encode.rb', line 372 def encode_reset(id, format = :msgpack) encode({type: "reset", session: "", id: id}, format) end |
.encode_screenshot(id, name, width = 1024, height = 768, format = :msgpack) ⇒ String
Capture rendered pixels.
356 357 358 359 360 361 |
# File 'lib/plushie/protocol/encode.rb', line 356 def encode_screenshot(id, name, width = 1024, height = 768, format = :msgpack) encode({ type: "screenshot", session: "", id: id, name: name, width: width, height: height }, format) end |
.encode_settings(settings, format = :msgpack) ⇒ String
Encode application-level settings. Sent as the first message.
All fields inside settings are optional. See protocol.md for the full list: protocol_version, default_text_size, default_font, antialiasing, vsync, fonts, scale_factor, validate_props, extension_config, default_event_rate, required_widgets.
49 50 51 52 53 |
# File 'lib/plushie/protocol/encode.rb', line 49 def encode_settings(settings, format = :msgpack) merged = {protocol_version: Protocol::PROTOCOL_VERSION}.merge(settings) merged = normalize_default_font(merged) encode({type: "settings", session: "", settings: merged}, format) end |
.encode_snapshot(tree, format = :msgpack) ⇒ String
Replace the entire UI tree.
80 81 82 |
# File 'lib/plushie/protocol/encode.rb', line 80 def encode_snapshot(tree, format = :msgpack) encode({type: "snapshot", session: "", tree: tree}, format) end |
.encode_subscribe(kind, tag, format = :msgpack, max_rate: nil, window_id: nil) ⇒ String
Subscribe to an event category.
104 105 106 107 108 109 |
# File 'lib/plushie/protocol/encode.rb', line 104 def encode_subscribe(kind, tag, format = :msgpack, max_rate: nil, window_id: nil) msg = {type: "subscribe", session: "", kind: kind.to_s, tag: tag.to_s} msg[:max_rate] = max_rate if max_rate msg[:window_id] = window_id if window_id encode(msg, format) end |
.encode_system_op(op, payload, format = :msgpack) ⇒ String
Send a system-level operation not tied to a specific window.
Uses the unified +_op+ envelope: op-specific data lives under +payload+.
181 182 183 184 185 186 |
# File 'lib/plushie/protocol/encode.rb', line 181 def encode_system_op(op, payload, format = :msgpack) encode({ type: "system_op", session: "", op: op.to_s, payload: payload }, format) end |
.encode_system_query(op, payload, format = :msgpack) ⇒ String
Send a system-level query.
Uses the unified +_op+ envelope: query-specific data lives under +payload+.
196 197 198 199 200 201 |
# File 'lib/plushie/protocol/encode.rb', line 196 def encode_system_query(op, payload, format = :msgpack) encode({ type: "system_query", session: "", op: op.to_s, payload: payload }, format) end |
.encode_tree_hash(id, name, format = :msgpack) ⇒ String
Compute a SHA-256 hash of the renderer's current tree.
344 345 346 |
# File 'lib/plushie/protocol/encode.rb', line 344 def encode_tree_hash(id, name, format = :msgpack) encode({type: "tree_hash", session: "", id: id, name: name}, format) end |
.encode_unregister_effect_stub(kind, format = :msgpack) ⇒ String
Remove a previously registered effect stub.
410 411 412 |
# File 'lib/plushie/protocol/encode.rb', line 410 def encode_unregister_effect_stub(kind, format = :msgpack) encode({type: "unregister_effect_stub", session: "", kind: kind.to_s}, format) end |
.encode_unsubscribe(kind, tag: nil, format: :msgpack) ⇒ String
Unsubscribe from an event category.
117 118 119 120 121 |
# File 'lib/plushie/protocol/encode.rb', line 117 def encode_unsubscribe(kind, tag: nil, format: :msgpack) msg = {type: "unsubscribe", session: "", kind: kind.to_s} msg[:tag] = tag.to_s if tag encode(msg, format) end |
.encode_widget_op(op, payload, format = :msgpack) ⇒ String
Perform an operation on a widget (focus, scroll, etc.).
133 134 135 |
# File 'lib/plushie/protocol/encode.rb', line 133 def (op, payload, format = :msgpack) encode({type: "widget_op", session: "", op: op.to_s, payload: payload}, format) end |
.encode_window_op(op, window_id, payload, format = :msgpack) ⇒ String
Manage a window (open, close, resize, etc.).
Uses the unified +_op+ envelope: op-specific data lives under +payload+; the +window_id+ addressing field stays flat beside +op+.
166 167 168 169 170 171 |
# File 'lib/plushie/protocol/encode.rb', line 166 def encode_window_op(op, window_id, payload, format = :msgpack) encode({ type: "window_op", session: "", op: op.to_s, window_id: window_id, payload: payload }, format) end |
.normalize_default_font(settings) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The renderer reads +default_font+ strictly as an object with at least a +family+ key; a bare string is silently dropped and the renderer falls back to the platform default. The Font encoder returns a string for the +:default+ and +:monospace+ shorthands but a hash for everything else, so wrap any string result back into the canonical +...+ shape.
63 64 65 66 67 68 69 |
# File 'lib/plushie/protocol/encode.rb', line 63 def normalize_default_font(settings) return settings unless settings.key?(:default_font) encoded = Type::Font.encode(settings[:default_font]) encoded = {family: encoded} if encoded.is_a?(String) settings.merge(default_font: encoded) end |
.stringify_keys(obj) ⇒ Object
Recursively convert all symbol keys to strings.
422 423 424 425 426 427 428 429 430 431 |
# File 'lib/plushie/protocol/encode.rb', line 422 def stringify_keys(obj) case obj when Hash obj.each_with_object({}) { |(k, v), h| h[k.to_s] = stringify_keys(v) } when Array obj.map { |v| stringify_keys(v) } else obj end end |