File cdr_types.hpp

File List > astutedds > cdr > cdr_types.hpp

Go to the documentation of this file


#ifndef ASTUTEDDS_CDR_TYPES_HPP
#define ASTUTEDDS_CDR_TYPES_HPP

#include <bit>
#include <cstdint>
#include <span>
#include <vector>
#include <stdexcept>
#ifdef _MSC_VER
#include <cstdlib>
#endif

namespace astutedds::cdr {

// CDR Encoding Version (7.4.3.4.2)
enum class EncodingKind : uint16_t {
    CDR_BE = 0x0000,           // CDR Big Endian
    CDR_LE = 0x0001,           // CDR Little Endian
    PL_CDR_BE = 0x0002,        // Parameter List CDR Big Endian
    PL_CDR_LE = 0x0003,        // Parameter List CDR Little Endian
    // XCDR2 / CDR2 encapsulations (DDS-XTypes 1.3, Table 34)
    CDR2_BE = 0x0006,          // PLAIN_CDR2 Big Endian (FINAL types)
    CDR2_LE = 0x0007,          // PLAIN_CDR2 Little Endian (FINAL types)
    XCDR2_BE = 0x0006,         // Alias for PLAIN_CDR2 Big Endian
    XCDR2_LE = 0x0007,         // Alias for PLAIN_CDR2 Little Endian
    D_CDR2_BE = 0x0008,        // Delimited XCDR2 Big Endian (APPENDABLE types)
    D_CDR2_LE = 0x0009,        // Delimited XCDR2 Little Endian (APPENDABLE types)
    PL_CDR2_BE = 0x000A,       // Parameter List XCDR2 Big Endian (MUTABLE types)
    PL_CDR2_LE = 0x000B,       // Parameter List XCDR2 Little Endian (MUTABLE types)
    XML = 0x0016               // XML encoding
};

// Extensibility Kind (7.2.2.4)
enum class ExtensibilityKind : uint8_t {
    FINAL = 0,
    APPENDABLE = 1,
    MUTABLE = 2
};

// Encapsulation Header (7.4.3.4.1)
struct EncapsulationHeader {
    EncodingKind encoding{EncodingKind::CDR_LE};
    uint16_t options{0};
};

// DHEADER for delimited (XCDR2) encoding (7.4.3.4.3)
struct DHEADER {
    uint32_t size{0};  // Size of the serialized object in bytes
};

// EMHEADER for mutable members (7.4.3.4.4)
struct EMHEADER {
    bool must_understand{false};
    bool length_code{false};  // 0 = 4-byte length, 1 = 8-byte length
    uint32_t member_id{0};
    uint32_t member_length{0};
};

// Type support for compile-time alignment calculations
template<typename T>
constexpr size_t alignment_of() {
    return alignof(T);
}

// Alignment utilities for CDR encoding
constexpr size_t align_offset(size_t offset, size_t alignment) {
    return (offset + alignment - 1) & ~(alignment - 1);
}

// CDR Stream buffer wrapper
class CDRBuffer {
public:
    explicit CDRBuffer(std::vector<uint8_t>& data) : data_(data) {}

    std::span<uint8_t> span() { return data_; }
    std::span<const uint8_t> span() const { return data_; }

    size_t size() const { return data_.size(); }
    void resize(size_t new_size) { data_.resize(new_size); }

    uint8_t* data() { return data_.data(); }
    const uint8_t* data() const { return data_.data(); }

private:
    std::vector<uint8_t>& data_;
};

// ---------------------------------------------------------------------------
// Encapsulation header helpers
// ---------------------------------------------------------------------------

inline EncodingKind detect_encoding(const std::vector<uint8_t> &buf)
{
    if (buf.size() < 2)
        return EncodingKind::CDR_LE; // safe fallback
    return static_cast<EncodingKind>((static_cast<uint16_t>(buf[0]) << 8) | buf[1]);
}

inline bool is_xcdr1(EncodingKind kind)
{
    return kind == EncodingKind::CDR_BE || kind == EncodingKind::CDR_LE ||
           kind == EncodingKind::PL_CDR_BE || kind == EncodingKind::PL_CDR_LE;
}

// Endianness detection and conversion
constexpr bool is_little_endian() {
    return std::endian::native == std::endian::little;
}

template<typename T>
T swap_endian(T value) {
    if constexpr (sizeof(T) == 1) {
        return value;
    } else if constexpr (sizeof(T) == 2) {
#if defined(_MSC_VER)
        return static_cast<T>(_byteswap_ushort(static_cast<uint16_t>(value)));
#else
        return static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(value)));
#endif
    } else if constexpr (sizeof(T) == 4) {
#if defined(_MSC_VER)
        return static_cast<T>(_byteswap_ulong(static_cast<uint32_t>(value)));
#else
        return static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(value)));
#endif
    } else if constexpr (sizeof(T) == 8) {
#if defined(_MSC_VER)
        return static_cast<T>(_byteswap_uint64(static_cast<uint64_t>(value)));
#else
        return static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(value)));
#endif
    }
}

} // namespace astutedds::cdr

#endif // ASTUTEDDS_CDR_TYPES_HPP