Skip to content

Add Pluggable Codec System for Request/Response Serialization #209

@om26er

Description

@om26er

Problem

Right now, the library handles message serialization in a fixed format (e.g., JSON or MessagePack).
We’d like to make it possible to pass structured objects (like Protobuf or Cap’n Proto messages) into WAMP calls and get objects back — with minimal boilerplate.

Example desired API:

result = await session.call(
    "com.example.process",
    MyInputProto(id=123),
    out_type=MyOutputProto,
)

This should:

  • Serialize MyInputProto to bytes using the selected codec.
  • Send the bytes over WAMP.
  • Decode the response into MyOutputProto automatically.

🧩 Codec Interface

from typing import Any, Generic, Type, TypeVar

T = TypeVar("T")

class Codec(Generic[T]):
    name: str

    def encode(self, obj: Any) -> bytes:
        """Serialize a Python object to bytes."""
        raise NotImplementedError

    def decode(self, data: bytes, out_type: Type[T]) -> T:
        """Deserialize bytes into an instance of out_type."""
        raise NotImplementedError

✅ Example Implementations

Protobuf

from google.protobuf.message import Message

class ProtobufCodec(Codec):
    name = "protobuf"

    def encode(self, obj: Message) -> bytes:
        return obj.SerializeToString()

    def decode(self, data: bytes, out_type: Type[Message]) -> Message:
        msg = out_type()
        msg.ParseFromString(data)
        return msg

Cap’n Proto

import capnp

class CapnpCodec(Codec):
    name = "capnp"

    def encode(self, obj) -> bytes:
        return obj.to_bytes_packed()

    def decode(self, data: bytes, out_type):
        return out_type.from_bytes_packed(data)

⚙️ Integrating with the WAMP Session

class Session:
    def __init__(self,):
        self.codec = None

    def set_payload_codec(codec: Codec):
        self.codec = codec

    async def call(self, uri: str, in_obj: Any, out_type: Type[Any]) -> Any:
        payload = self.codec.encode(in_obj)
        raw = await self._send_and_receive(uri, payload)
        return self.codec.decode(raw, out_type)

Usage:

session = Session(codec=ProtobufCodec())
result = await session.call("com.example.add", MyRequest(a=2, b=3), MyResponse)

Switching codecs is trivial:

session.codec = CapnpCodec()

✅ Benefits

Benefit Description
🔌 Extensible Users can plug in new codecs (e.g. JSON, FlatBuffers)
🧠 Clean Transport code remains format-agnostic
⚙️ Flexible Codec can be changed dynamically or negotiated at runtime
🧾 Reusable Can also be reused for publish/subscribe and registration calls

Summary

Add a codec abstraction to the WAMP session layer to allow encode()/decode() handling to be pluggable.
This enables passing and returning Protobuf, Cap’n Proto, or other structured data seamlessly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions