File typed.hpp

File List > astutedds > dcps > typed.hpp

Go to the documentation of this file

//
// Copyright (c) 2026, Astute Systems PTY LTD
//
// This file is part of the Astute DDS developed by Astute Systems.
//
// See the commercial LICENSE file in the project root for full license details.
//

#ifndef ASTUTEDDS_DCPS_TYPED_HPP
#define ASTUTEDDS_DCPS_TYPED_HPP

#include <astutedds/cdr/cdr_types.hpp>
#include <astutedds/cdr/xcdr1_codec.hpp>
#include <astutedds/cdr/xcdr2_codec.hpp>
#include <astutedds/dcps/dcps.hpp>

#include <vector>

namespace astutedds::dcps
{
// Lightweight typed wrapper that serializes to both XCDR1 and XCDR2 so the
// transport can choose the encoding that matches the remote reader.
template <typename T, typename XCDR2Codec, typename XCDR1Codec = XCDR2Codec>
class TypedDataWriter
{
public:
    explicit TypedDataWriter(DataWriter* writer) : writer_(writer) {}

    bool write(const T& sample)
    {
        if (!writer_)
            return false;

        std::vector<uint8_t> xcdr1, xcdr2;
        {
            astutedds::cdr::XCDR1Encoder enc(xcdr1);
            if (!XCDR1Codec::serialize(enc, sample))
                return false;
        }
        {
            astutedds::cdr::XCDR2Encoder enc(xcdr2, false,
                                             astutedds::cdr::ExtensibilityKind::APPENDABLE);
            if (!XCDR2Codec::serialize(enc, sample))
                return false;
        }

        return writer_->write(xcdr1, xcdr2);
    }

    DataWriter* raw() const { return writer_; }

private:
    DataWriter* writer_{nullptr};
};

// Lightweight typed reader: inspects the encapsulation header to choose the
// correct codec rather than blind try/catch.
template <typename T, typename XCDR2Codec, typename XCDR1Codec = XCDR2Codec>
class TypedDataReader
{
public:
    explicit TypedDataReader(DataReader* reader) : reader_(reader) {}

    ReturnCode_t take_next(T& out, SampleInfo& info)
    {
        return next_impl(out, info, /*remove=*/true);
    }

    ReturnCode_t read_next(T& out, SampleInfo& info)
    {
        return next_impl(out, info, /*remove=*/false);
    }

    static bool deserialize(const std::vector<uint8_t>& buf, T& out)
    {
        if (buf.size() < 4)
            return false;
        if (cdr::is_xcdr1(cdr::detect_encoding(buf)))
        {
            astutedds::cdr::XCDR1Decoder dec(buf);
            return XCDR1Codec::deserialize(dec, out);
        }
        astutedds::cdr::XCDR2Decoder dec(buf);
        return XCDR2Codec::deserialize(dec, out);
    }

    DataReader* raw() const { return reader_; }

private:
    ReturnCode_t next_impl(T& out, SampleInfo& info, bool remove)
    {
        if (!reader_)
            return ReturnCode_t::RETCODE_BAD_PARAMETER;
        std::vector<uint8_t> data;
        auto rc = remove ? reader_->take_next_sample(data, info)
                         : reader_->read_next_sample(data, info);
        if (rc != ReturnCode_t::RETCODE_OK)
            return rc;
        if (!info.valid_data || data.empty())
            return ReturnCode_t::RETCODE_NO_DATA;

        return deserialize(data, out) ? ReturnCode_t::RETCODE_OK
                                      : ReturnCode_t::RETCODE_ERROR;
    }

    DataReader* reader_{nullptr};
};
}  // namespace astutedds::dcps

#endif  // ASTUTEDDS_DCPS_TYPED_HPP