shared_ptr directly with zero copying.
The Serializer interface
All serializers inherit from basis::core::serialization::Serializer and implement three static template methods:
SerializationHandler<T> — type deduction
SerializationHandler<T_MSG> is the mechanism that maps a message type to its serializer. The primary template is intentionally left as a static_assert:
SerializationHandler directly — you use it as a type alias:
Built-in plugins
Protobuf plugin
Header:basis/plugins/serialization/protobuf.hYAML prefix:
protobuf:Serializer ID:
"protobuf"
SerializationHandler specialization activates for any type that inherits from google::protobuf::Message:
protobuf.h is sufficient — you do not need to call any registration function.
MCAP encoding: "protobuf" for both schema and message.
Schema format: A serialized google::protobuf::FileDescriptorSet containing all transitive dependencies of the message descriptor. This allows the MCAP recorder to store enough information to decode messages without the original .proto files.
ROS1 msg plugin
Header:basis/plugins/serialization/rosmsg.hYAML prefix:
rosmsg:Serializer ID:
"rosmsg"
ros::message_traits::IsMessage<T>:
"ros1" for messages, "ros1msg" for schemas.
Schema format: The ROS message definition string, obtained via ros::message_traits::Definition<T>::value(). The MD5 hash is stored as basis_hash_id in MCAP channel metadata.
Raw serializer
YAML prefix:raw:Class:
basis::core::serialization::RawSerializer
Treats the message as a flat byte buffer using memcpy. Only safe for plain-old-data (POD) structs with no pointers. Does not support schema introspection or MCAP schema encoding.
Type identification on the wire — MessageTypeInfo
When a publisher advertises a topic, it registers the type’s identity with the coordinator and embeds it in network packets. The identity is described by MessageTypeInfo:
SchemaId() is the canonical wire identifier for a topic’s message type. It matches the serializer:CppType syntax used in the unit YAML type field (after C++ :: separators are applied).
Subscribers use the SchemaId() to verify type compatibility and to hand off schema information to the MCAP recorder.
On-demand serialization
A key design goal of Basis is that serialization is lazy. When a publisher callsPublish(msg):
- Inproc subscribers in the same process receive a
std::shared_ptr<const T_MSG>directly — no serialization occurs. - Network subscribers trigger serialization once per packet, regardless of how many remote subscribers are listening.
- The recorder receives the already-serialized bytes when they exist, or triggers serialization on demand.
Specifying the serializer in YAML
In a.unit.yaml file, every type field uses the serializer:CppType format:
type string on the first :, uses the prefix to select the #include for the serializer header, and applies .→:: substitution on the type name for protobuf package paths.
- protobuf example
- rosmsg example
<basis/plugins/serialization/protobuf.h> and uses geometry::Pose as the C++ type.Writing a custom serializer
To add a new serializer:Implement the Serializer interface
Create a class that implements
GetSerializedSize, SerializeToSpan, and DeserializeFromSpan as static template methods. Define a SERIALIZER_ID string constant.Add a SerializationHandler specialization
Specialize
basis::SerializationHandler for your message family. The Enable parameter lets you use type traits to match an entire family.Wrap in a SerializationPlugin (optional)
If you want runtime schema loading and message introspection (required for MCAP recording), wrap your serializer in Register an instance of this plugin with the recorder at startup.
AutoSerializationPlugin:Plugin summary
| YAML prefix | Serializer class | Activates for | MCAP encoding |
|---|---|---|---|
protobuf: | ProtobufSerializer | google::protobuf::Message subclasses | protobuf / protobuf |
rosmsg: | RosmsgSerializer | ros::message_traits::IsMessage<T> types | ros1 / ros1msg |
raw: | RawSerializer | POD structs (explicit use only) | none |
Next steps
Unit YAML reference
How to specify the serializer prefix in input and output type fields
Code generation
How the generator includes serializer headers and wires up deserialization helpers
Transport
How the transport layer invokes serialization for network delivery
Recording and replay
How MessageSchema and MessageTypeInfo are used when writing MCAP files