Dala.Plugin.Protocol (dala v0.1.1)

Copy Markdown View Source

Generates binary protocol specifications from plugin schemas.

This module auto-generates field mappings and encoders for plugin-defined properties, preventing protocol chaos through systematic field numbering.

Field Numbering

Each property in a component gets a unique field number:

prop "volume", :f32
# → FIELD_VOLUME = 0x07
# → [f32]

Field numbers are assigned sequentially starting from 0x01 for each component, ensuring no collisions within a plugin.

Binary Format

The protocol uses a compact binary format:

+--------+--------+--------+--------+
| opcode |  id    | field  | value  |
+--------+--------+--------+--------+
  1 byte  8 bytes  1 byte  N bytes

Where:

  • opcode: CREATE_NODE, UPDATE_PROP, etc.
  • id: 64-bit node identifier
  • field: field number (0x01-0xFF)
  • value: type-encoded value

Type Encoding

TypeTagSizeFormat
string0x01varUTF-8 + len
bool0x0210x00/0x01
int0x038signed 64-bit
float0x04864-bit IEEE
f320x05432-bit IEEE
f640x06864-bit IEEE
color0x074ARGB
binary0x08varlen + data

Capability Negotiation & Lifecycle Events

The protocol also encodes capability negotiation and lifecycle events:

# Capability negotiation
encode_capability_negotiation([:gestures, :animation], [:gestures, :accessibility, :animation])
# → binary with requested + provided capabilities

# Lifecycle events
encode_lifecycle_event(:init, %{opts: []})
encode_lifecycle_event(:activate, %{})
encode_lifecycle_event(:cleanup, %{})

Example

defmodule MyApp.VideoPlugin do
  use Dala.Plugin

  component "video" do
    prop "source", :string
    prop "volume", :f32
    prop "autoplay", :bool
  end
end

Generates:

FIELD_SOURCE = 0x01
FIELD_VOLUME = 0x02
FIELD_AUTOPLAY = 0x03

# Encoding {"video.mp4", 0.8, true}:
# 01 00 00 00 00 00 00 00 00  # id (8 bytes)
# 01 0B 76 69 64 65 6F 2E 6D  # field 01, string "video.mp4"
# 70 02 00 00 00 00 02 03 10  # field 02, f32 0.8
# 03 01                       # field 03, bool true

Summary

Functions

Builds a global field map for quick lookup.

Decodes a binary event message back to a map.

Encodes a capability negotiation message.

Encodes a typed event message for the native bridge.

Encodes a lifecycle event message.

Encodes a property update for a node.

Encodes a value according to its type tag.

Generates example encoded data for documentation.

Generates protocol specification for a plugin.

Generates field mappings for a single component.

Converts a prop type to its binary type tag.

Types

field_number()

@type field_number() :: 0..255

type_tag()

@type type_tag() :: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10

Functions

build_field_map(components)

@spec build_field_map([map()]) :: %{required(String.t()) => map()}

Builds a global field map for quick lookup.

decode_event(arg)

@spec decode_event(binary()) :: {atom(), map()}

Decodes a binary event message back to a map.

encode_capability_negotiation(requested, provided)

@spec encode_capability_negotiation([atom()], [atom()]) :: binary()

Encodes a capability negotiation message.

The binary format is:

  • 1 byte: capability opcode (0xF1)
  • 2 bytes: count of requested capabilities
  • For each capability: 2 bytes length + UTF-8 name
  • 2 bytes: count of provided capabilities
  • For each capability: 2 bytes length + UTF-8 name

encode_event(event, payload)

@spec encode_event(atom(), map()) :: binary()

Encodes a typed event message for the native bridge.

The binary format is:

  • 1 byte: event opcode (0xF2)
  • 2 bytes: event name length
  • N bytes: event name (UTF-8)
  • 2 bytes: field count
  • For each field:
    • 2 bytes: field name length
    • N bytes: field name (UTF-8)
    • 1 byte: type tag
    • N bytes: value

encode_lifecycle_event(event, payload)

@spec encode_lifecycle_event(atom(), map()) :: binary()

Encodes a lifecycle event message.

The binary format is:

  • 1 byte: lifecycle opcode (0xF0)
  • 2 bytes: event name length
  • N bytes: event name (UTF-8)
  • 4 bytes: payload length
  • M bytes: payload (JSON-encoded)

encode_prop_update(node_id, field_number, type_tag, value)

@spec encode_prop_update(String.t(), field_number(), type_tag(), term()) :: binary()

Encodes a property update for a node.

encode_value(arg1, value)

@spec encode_value(type_tag(), term()) :: binary()

Encodes a value according to its type tag.

example_encoding(component)

@spec example_encoding(Dala.Plugin.Component.t()) :: String.t()

Generates example encoded data for documentation.

generate(plugin)

@spec generate(Dala.Plugin.t()) :: map()

Generates protocol specification for a plugin.

Returns a map containing field mappings and encoding helpers.

generate_component(component)

@spec generate_component(Dala.Plugin.Component.t()) :: map()

Generates field mappings for a single component.

type_to_tag(atom)

@spec type_to_tag(Dala.Plugin.Component.prop_type()) :: type_tag()

Converts a prop type to its binary type tag.