File serialization.hpp
File List > astutedds > rmw > serialization.hpp
Go to the documentation of this file
//
// Copyright (c) 2026, Astute Systems PTY LTD
//
// This file is part of the AstuteDDS RMW implementation.
//
// See the commercial LICENSE file in the project root for full license details.
//
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <type_traits>
#include <vector>
#include <astutedds/rmw/type_support.hpp>
// ---------------------------------------------------------------------------
// Writer-side primitives
// ---------------------------------------------------------------------------
inline void
cdr_pad(std::vector<uint8_t> & buf, std::size_t align)
{
const std::size_t rem = buf.size() % align;
if (rem)
{
buf.insert(buf.end(), align - rem, 0u);
}
}
template<typename T>
inline void
cdr_write_le(std::vector<uint8_t> & buf, T val)
{
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
const uint8_t * p = reinterpret_cast<const uint8_t *>(&val);
buf.insert(buf.end(), p, p + sizeof(T));
}
// ---------------------------------------------------------------------------
// Reader-side primitive
// ---------------------------------------------------------------------------
template<typename T>
inline void
cdr_byteswap_inplace(T & v)
{
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
auto * p = reinterpret_cast<uint8_t *>(&v);
for (std::size_t i = 0, j = sizeof(T) - 1; i < j; ++i, --j)
{
const uint8_t tmp = p[i];
p[i] = p[j];
p[j] = tmp;
}
}
struct CdrReader
{
const uint8_t * buf;
std::size_t len;
std::size_t pos;
bool swap_bytes { false };
void align(std::size_t a)
{
const std::size_t abs = pos + 4;
const std::size_t rem = abs % a;
if (rem) { pos += a - rem; }
}
bool read_u8(uint8_t & v)
{
if (pos >= len) { return false; }
v = buf[pos++];
return true;
}
bool read_u16(uint16_t & v)
{
align(2);
if (pos + 2 > len) { return false; }
std::memcpy(&v, buf + pos, 2);
if (swap_bytes) { cdr_byteswap_inplace(v); }
pos += 2;
return true;
}
bool read_u32(uint32_t & v)
{
align(4);
if (pos + 4 > len) { return false; }
std::memcpy(&v, buf + pos, 4);
if (swap_bytes) { cdr_byteswap_inplace(v); }
pos += 4;
return true;
}
bool read_u64(uint64_t & v)
{
align(8);
if (pos + 8 > len) { return false; }
std::memcpy(&v, buf + pos, 8);
if (swap_bytes) { cdr_byteswap_inplace(v); }
pos += 8;
return true;
}
bool read_bytes(void * dst, std::size_t n)
{
if (pos + n > len) { return false; }
std::memcpy(dst, buf + pos, n);
pos += n;
return true;
}
};
// ---------------------------------------------------------------------------
// Mutually-recursive message encode / decode entry points
// (defined in serialization.cpp)
// ---------------------------------------------------------------------------
bool
cdr_encode_c_message(
const MembersC * members,
const void * msg,
std::vector<uint8_t> & buf);
bool
cdr_decode_c_message(
const MembersC * members,
CdrReader & rdr,
void * msg);
bool
cdr_encode_cpp_message(
const MembersCpp * members,
const void * msg,
std::vector<uint8_t> & buf);
bool
cdr_decode_cpp_message(
const MembersCpp * members,
CdrReader & rdr,
void * msg);
// ---------------------------------------------------------------------------
// Public serialize / deserialize wrappers
// ---------------------------------------------------------------------------
bool
serialize_message(
const TypeSupportHandle & ts,
const void * ros_message,
std::vector<uint8_t> & out);
bool
deserialize_message(
const TypeSupportHandle & ts,
const uint8_t * data,
size_t len,
void * ros_message);