Canopy uses YAS (Yet Another Serialization) as its primary serialization framework, supporting binary, compressed binary, and JSON formats.
| Format | Type | Use Case |
|---|---|---|
yas_binary |
Binary | High-performance, small payloads |
yas_compressed_binary |
Binary + compression | Large payloads, network transfer |
yas_json |
JSON text | Debugging, interoperability |
// In IDL or build configuration
encoding = {
yas_binary,
yas_compressed_binary,
yas_json
}#include <rpc/internal/serialiser.h>
// Serialize an object
my_struct obj{42, "hello"};
auto serialized = rpc::serialise(obj, rpc::encoding::yas_binary);
// Deserialize
rpc::span data(serialized);
my_struct deserialized;
auto error = rpc::deserialise(rpc::encoding::yas_binary, data, deserialized);auto size = rpc::get_saved_size(obj, rpc::encoding::yas_binary);If an encoding is not supported, Canopy falls back to yas_json:
// Client requests binary
auto error = CO_AWAIT proxy_->send(
protocol_version,
rpc::encoding::yas_binary, // Requested
tag,
interface_id,
method_id,
input_buffer,
output_buffer);
// Server supports only JSON
// Response uses yas_json automatically// Force specific encoding
auto error = CO_AWAIT proxy_->send(
protocol_version,
rpc::encoding::yas_json, // Explicit choice
tag,
interface_id,
method_id,
input_buffer,
output_buffer);| IDL Type | Serialized As |
|---|---|
int, int32_t |
32-bit integer |
int64_t |
64-bit integer |
uint32_t, uint64_t |
Unsigned integer |
float, double |
IEEE 754 float |
bool |
1 byte (0/1) |
std::string |
Length + UTF-8 bytes |
| IDL Type | Serialized As |
|---|---|
std::vector<T> |
Length + elements |
std::list<T> |
Length + elements |
std::map<K,V> |
Length + (key, value) pairs |
std::array<T,N> |
Fixed number of elements |
std::optional<T> |
Present flag + value |
struct person
{
std::string name;
int age;
std::vector<std::string> hobbies;
};YAS Binary: Optimized binary format with type information YAS JSON: JSON object with field names
Canopy automatically generates JSON schemas for all interfaces:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "calculator",
"definitions": {
"i_calculator_add_send": {
"type": "object",
"description": "Parameters for add from interface i_calculator",
"properties": {
"a": { "type": "integer" },
"b": { "type": "integer" }
},
"required": ["a", "b"],
"additionalProperties": false
},
"i_calculator_add_receive": {
"type": "object",
"description": "Result for add from interface i_calculator",
"properties": {
"result": { "type": "integer" },
"return_value": { "type": "integer" }
},
"required": ["result", "return_value"],
"additionalProperties": false
}
}
}// Get function info including schemas
auto functions = xxx::i_calculator::get_function_info();
for (const auto& func : functions)
{
std::cout << "Function: " << func.name << "\n";
std::cout << "Input schema: " << func.in_json_schema << "\n";
std::cout << "Output schema: " << func.out_json_schema << "\n";
}namespace rpc
{
template<>
struct serialiser<my_custom_type, custom_encoding>
{
static std::vector<uint8_t> serialise(const my_custom_type& obj)
{
// Custom serialization logic
std::vector<uint8_t> result;
// ... serialize to result
return result;
}
static error_code deserialise(const std::vector<uint8_t>& data,
my_custom_type& obj)
{
// Custom deserialization logic
// ... deserialize from data
return error::OK();
}
};
} // namespace rpc// In your serialization initialization
rpc::register_custom_serializer<my_custom_type, custom_encoding>(
&serialiser<my_custom_type, custom_encoding>::serialise,
&serialiser<my_custom_type, custom_encoding>::deserialise);| Scenario | Recommended Format |
|---|---|
| High-performance local | yas_binary |
| Network transfer | yas_compressed_binary |
| Debugging/inspection | yas_json |
yas_binary: 100 bytes (baseline)
yas_compressed_binary: 60 bytes (compressed)
yas_json: 200 bytes (text)
yas_binary: 0.1 ms (fastest)
yas_compressed_binary: 0.5 ms (compression overhead)
yas_json: 1.0 ms (slowest)
auto error = rpc::deserialise(enc, data, obj);
switch (error)
{
case rpc::error::OK():
// Success
break;
case rpc::error::PROXY_DESERIALISATION_ERROR():
// Failed to deserialize proxy
break;
case rpc::error::STUB_DESERIALISATION_ERROR():
// Failed to deserialize stub
break;
case rpc::error::INCOMPATIBLE_SERIALISATION():
// Unsupported encoding format
break;
}- Use binary formats for production
- Use JSON for debugging when inspecting traffic
- Enable compression for large payloads over network
- Test all formats during development
- Document format requirements for API consumers
- Protocol Buffers - Cross-language serialization
- Error Handling - Error code reference
- API Reference - Complete API