File qos.hpp

File List > astutedds > dcps > qos.hpp

Go to the documentation of this file


#ifndef ASTUTEDDS_DCPS_QOS_HPP
#define ASTUTEDDS_DCPS_QOS_HPP

#include <astutedds/rtps/rtps_types.hpp>
#include <string>
#include <vector>
#include <chrono>
#include <utility>

namespace astutedds::dcps
{

    // Durability QoS Policy (2.2.3.4)
    enum class DurabilityQosPolicyKind
    {
        VOLATILE_DURABILITY_QOS,
        TRANSIENT_LOCAL_DURABILITY_QOS,
        TRANSIENT_DURABILITY_QOS,
        PERSISTENT_DURABILITY_QOS
    };

    struct DurabilityQosPolicy
    {
        DurabilityQosPolicyKind kind{DurabilityQosPolicyKind::VOLATILE_DURABILITY_QOS};

        bool operator==(const DurabilityQosPolicy&) const = default;
        bool operator!=(const DurabilityQosPolicy& o) const { return !(*this == o); }
    };

    // Reliability QoS Policy (2.2.3.12)
    enum class ReliabilityQosPolicyKind
    {
        BEST_EFFORT_RELIABILITY_QOS,
        RELIABLE_RELIABILITY_QOS
    };

    struct ReliabilityQosPolicy
    {
        ReliabilityQosPolicyKind kind{ReliabilityQosPolicyKind::BEST_EFFORT_RELIABILITY_QOS};
        rtps::Duration_t max_blocking_time{rtps::Time_t{0, 100000000}}; // 100ms default

        bool operator==(const ReliabilityQosPolicy&) const = default;
        bool operator!=(const ReliabilityQosPolicy& o) const { return !(*this == o); }
    };

    // History QoS Policy (2.2.3.8)
    enum class HistoryQosPolicyKind
    {
        KEEP_LAST_HISTORY_QOS,
        KEEP_ALL_HISTORY_QOS
    };

    struct HistoryQosPolicy
    {
        HistoryQosPolicyKind kind{HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS};
        int32_t depth{1};

        bool operator==(const HistoryQosPolicy&) const = default;
        bool operator!=(const HistoryQosPolicy& o) const { return !(*this == o); }
    };

    // Liveliness QoS Policy (2.2.3.10)
    enum class LivelinessQosPolicyKind
    {
        AUTOMATIC_LIVELINESS_QOS,
        MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,
        MANUAL_BY_TOPIC_LIVELINESS_QOS
    };

    struct LivelinessQosPolicy
    {
        LivelinessQosPolicyKind kind{LivelinessQosPolicyKind::AUTOMATIC_LIVELINESS_QOS};
        rtps::Duration_t lease_duration{rtps::Time_t::TIME_INFINITE()};

        bool operator==(const LivelinessQosPolicy&) const = default;
        bool operator!=(const LivelinessQosPolicy& o) const { return !(*this == o); }
    };

    // Deadline QoS Policy (2.2.3.3)
    struct DeadlineQosPolicy
    {
        rtps::Duration_t period{rtps::Time_t::TIME_INFINITE()};

        bool operator==(const DeadlineQosPolicy&) const = default;
        bool operator!=(const DeadlineQosPolicy& o) const { return !(*this == o); }
    };

    // Ownership QoS Policy (2.2.3.11)
    enum class OwnershipQosPolicyKind
    {
        SHARED_OWNERSHIP_QOS,
        EXCLUSIVE_OWNERSHIP_QOS
    };

    struct OwnershipQosPolicy
    {
        OwnershipQosPolicyKind kind{OwnershipQosPolicyKind::SHARED_OWNERSHIP_QOS};

        bool operator==(const OwnershipQosPolicy&) const = default;
        bool operator!=(const OwnershipQosPolicy& o) const { return !(*this == o); }
    };

    // Ownership Strength QoS Policy
    struct OwnershipStrengthQosPolicy
    {
        int32_t value{0};

        bool operator==(const OwnershipStrengthQosPolicy&) const = default;
        bool operator!=(const OwnershipStrengthQosPolicy& o) const { return !(*this == o); }
    };

    // Partition QoS Policy (2.2.3.5)
    struct PartitionQosPolicy
    {
        std::vector<std::string> name;

        bool operator==(const PartitionQosPolicy&) const = default;
        bool operator!=(const PartitionQosPolicy& o) const { return !(*this == o); }
    };

    // Resource Limits QoS Policy (2.2.3.13)
    struct ResourceLimitsQosPolicy
    {
        int32_t max_samples{-1};              // unlimited
        int32_t max_instances{-1};            // unlimited
        int32_t max_samples_per_instance{-1}; // unlimited

        bool operator==(const ResourceLimitsQosPolicy&) const = default;
        bool operator!=(const ResourceLimitsQosPolicy& o) const { return !(*this == o); }
    };

    // User Data QoS Policy (2.2.3.2)
    struct UserDataQosPolicy
    {
        std::vector<uint8_t> value;

        bool operator==(const UserDataQosPolicy&) const = default;
        bool operator!=(const UserDataQosPolicy& o) const { return !(*this == o); }
    };

    // Topic Data QoS Policy
    struct TopicDataQosPolicy
    {
        std::vector<uint8_t> value;

        bool operator==(const TopicDataQosPolicy&) const = default;
        bool operator!=(const TopicDataQosPolicy& o) const { return !(*this == o); }
    };

    // Group Data QoS Policy
    struct GroupDataQosPolicy
    {
        std::vector<uint8_t> value;

        bool operator==(const GroupDataQosPolicy&) const = default;
        bool operator!=(const GroupDataQosPolicy& o) const { return !(*this == o); }
    };

    // Presentation QoS Policy (2.2.3.6)
    enum class PresentationQosPolicyAccessScopeKind
    {
        INSTANCE_PRESENTATION_QOS,
        TOPIC_PRESENTATION_QOS,
        GROUP_PRESENTATION_QOS
    };

    struct PresentationQosPolicy
    {
        PresentationQosPolicyAccessScopeKind access_scope{
            PresentationQosPolicyAccessScopeKind::INSTANCE_PRESENTATION_QOS};
        bool coherent_access{false};
        bool ordered_access{false};

        bool operator==(const PresentationQosPolicy&) const = default;
        bool operator!=(const PresentationQosPolicy& o) const { return !(*this == o); }
    };

    // Destination Order QoS Policy (2.2.3.7)
    enum class DestinationOrderQosPolicyKind
    {
        BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS,
        BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
    };

    struct DestinationOrderQosPolicy
    {
        DestinationOrderQosPolicyKind kind{
            DestinationOrderQosPolicyKind::BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS};

        bool operator==(const DestinationOrderQosPolicy&) const = default;
        bool operator!=(const DestinationOrderQosPolicy& o) const { return !(*this == o); }
    };

    // Data Representation QoS Policy (XTypes 7.6.3.5)
    struct DataRepresentationQosPolicy
    {
        std::vector<int16_t> value; // List of supported encodings

        bool operator==(const DataRepresentationQosPolicy&) const = default;
        bool operator!=(const DataRepresentationQosPolicy& o) const { return !(*this == o); }
    };

    // Latency Budget QoS Policy (2.2.3.9)
    struct LatencyBudgetQosPolicy
    {
        rtps::Duration_t duration{rtps::Time_t::TIME_ZERO()};

        bool operator==(const LatencyBudgetQosPolicy&) const = default;
        bool operator!=(const LatencyBudgetQosPolicy& o) const { return !(*this == o); }
    };

    // Transport Priority QoS Policy (2.2.3.14)
    struct TransportPriorityQosPolicy
    {
        int32_t value{0};

        bool operator==(const TransportPriorityQosPolicy&) const = default;
        bool operator!=(const TransportPriorityQosPolicy& o) const { return !(*this == o); }
    };

    // Lifespan QoS Policy (2.2.3.15)
    struct LifespanQosPolicy
    {
        rtps::Duration_t duration{rtps::Time_t::TIME_INFINITE()};

        bool operator==(const LifespanQosPolicy&) const = default;
        bool operator!=(const LifespanQosPolicy& o) const { return !(*this == o); }
    };

    // Time-Based Filter QoS Policy (2.2.3.16)
    struct TimeBasedFilterQosPolicy
    {
        rtps::Duration_t minimum_separation{rtps::Time_t::TIME_ZERO()};

        bool operator==(const TimeBasedFilterQosPolicy&) const = default;
        bool operator!=(const TimeBasedFilterQosPolicy& o) const { return !(*this == o); }
    };

    // Entity Factory QoS Policy (2.2.3.17)
    struct EntityFactoryQosPolicy
    {
        bool autoenable_created_entities{true};

        bool operator==(const EntityFactoryQosPolicy&) const = default;
        bool operator!=(const EntityFactoryQosPolicy& o) const { return !(*this == o); }
    };

    // Writer Data Lifecycle QoS Policy (2.2.3.18)
    struct WriterDataLifecycleQosPolicy
    {
        bool autodispose_unregistered_instances{true};

        bool operator==(const WriterDataLifecycleQosPolicy&) const = default;
        bool operator!=(const WriterDataLifecycleQosPolicy& o) const { return !(*this == o); }
    };

    // Reader Data Lifecycle QoS Policy (2.2.3.19)
    struct ReaderDataLifecycleQosPolicy
    {
        rtps::Duration_t autopurge_nowriter_samples_delay{rtps::Time_t::TIME_INFINITE()};
        rtps::Duration_t autopurge_disposed_samples_delay{rtps::Time_t::TIME_INFINITE()};

        bool operator==(const ReaderDataLifecycleQosPolicy&) const = default;
        bool operator!=(const ReaderDataLifecycleQosPolicy& o) const { return !(*this == o); }
    };

    // Durability Service QoS Policy (2.2.3.20)
    struct DurabilityServiceQosPolicy
    {
        rtps::Duration_t service_cleanup_delay{rtps::Time_t::TIME_ZERO()};
        HistoryQosPolicyKind history_kind{HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS};
        int32_t history_depth{1};
        int32_t max_samples{-1};
        int32_t max_instances{-1};
        int32_t max_samples_per_instance{-1};

        bool operator==(const DurabilityServiceQosPolicy&) const = default;
        bool operator!=(const DurabilityServiceQosPolicy& o) const { return !(*this == o); }
    };

    // Combined QoS structures
    struct DomainParticipantQos
    {
        UserDataQosPolicy user_data;
        EntityFactoryQosPolicy entity_factory;

        bool operator==(const DomainParticipantQos&) const = default;
        bool operator!=(const DomainParticipantQos& o) const { return !(*this == o); }
    };

    struct TopicQos
    {
        TopicDataQosPolicy topic_data;
        DurabilityQosPolicy durability;
        DurabilityServiceQosPolicy durability_service;
        DeadlineQosPolicy deadline;
        LatencyBudgetQosPolicy latency_budget;
        LivelinessQosPolicy liveliness;
        ReliabilityQosPolicy reliability;
        DestinationOrderQosPolicy destination_order;
        HistoryQosPolicy history;
        ResourceLimitsQosPolicy resource_limits;
        TransportPriorityQosPolicy transport_priority;
        LifespanQosPolicy lifespan;
        OwnershipQosPolicy ownership;
        DataRepresentationQosPolicy representation;

        bool operator==(const TopicQos&) const = default;
        bool operator!=(const TopicQos& o) const { return !(*this == o); }
    };

    struct PublisherQos
    {
        PresentationQosPolicy presentation;
        PartitionQosPolicy partition;
        GroupDataQosPolicy group_data;

        bool operator==(const PublisherQos&) const = default;
        bool operator!=(const PublisherQos& o) const { return !(*this == o); }
    };

    struct SubscriberQos
    {
        PresentationQosPolicy presentation;
        PartitionQosPolicy partition;
        GroupDataQosPolicy group_data;

        bool operator==(const SubscriberQos&) const = default;
        bool operator!=(const SubscriberQos& o) const { return !(*this == o); }
    };

    struct DataWriterQos
    {
        DurabilityQosPolicy durability;
        DurabilityServiceQosPolicy durability_service;
        DeadlineQosPolicy deadline;
        LatencyBudgetQosPolicy latency_budget;
        LivelinessQosPolicy liveliness;
        ReliabilityQosPolicy reliability;
        DestinationOrderQosPolicy destination_order;
        HistoryQosPolicy history;
        ResourceLimitsQosPolicy resource_limits;
        TransportPriorityQosPolicy transport_priority;
        LifespanQosPolicy lifespan;
        OwnershipQosPolicy ownership;
        OwnershipStrengthQosPolicy ownership_strength;
        WriterDataLifecycleQosPolicy writer_data_lifecycle;
        UserDataQosPolicy user_data;
        DataRepresentationQosPolicy representation;

        bool operator==(const DataWriterQos&) const = default;
        bool operator!=(const DataWriterQos& o) const { return !(*this == o); }
    };

    struct DataReaderQos
    {
        DurabilityQosPolicy durability;
        DeadlineQosPolicy deadline;
        LatencyBudgetQosPolicy latency_budget;
        LivelinessQosPolicy liveliness;
        TimeBasedFilterQosPolicy time_based_filter;
        ReliabilityQosPolicy reliability;
        DestinationOrderQosPolicy destination_order;
        HistoryQosPolicy history;
        ResourceLimitsQosPolicy resource_limits;
        OwnershipQosPolicy ownership;
        ReaderDataLifecycleQosPolicy reader_data_lifecycle;
        UserDataQosPolicy user_data;
        DataRepresentationQosPolicy representation;

        bool operator==(const DataReaderQos&) const = default;
        bool operator!=(const DataReaderQos& o) const { return !(*this == o); }
    };

    // Simple QoS manipulators to enable fluent QoS composition (DataWriter/Reader)
    struct ReliabilityQosModifier
    {
        ReliabilityQosPolicyKind kind;
        rtps::Duration_t max_blocking_time;
    };

    struct HistoryKeepLastModifier
    {
        int32_t depth;
    };

    struct DurabilityQosModifier
    {
        DurabilityQosPolicyKind kind;
    };

    struct DataRepresentationModifier
    {
        std::vector<int16_t> value;
    };

    inline ReliabilityQosModifier Reliability(ReliabilityQosPolicyKind kind,
                                              rtps::Duration_t max_blocking_time = rtps::Duration_t{0, 100000000})
    {
        return ReliabilityQosModifier{kind, max_blocking_time};
    }

    inline HistoryKeepLastModifier HistoryKeepLast(int32_t depth)
    {
        return HistoryKeepLastModifier{depth};
    }

    inline DurabilityQosModifier Durability(DurabilityQosPolicyKind kind)
    {
        return DurabilityQosModifier{kind};
    }

    inline DataRepresentationModifier DataRepresentation(std::vector<int16_t> value)
    {
        return DataRepresentationModifier{std::move(value)};
    }

    // Enable chaining: qos << Reliability(...) << HistoryKeepLast(...)
    inline DataWriterQos operator<<(DataWriterQos qos, const ReliabilityQosModifier &mod)
    {
        qos.reliability.kind = mod.kind;
        qos.reliability.max_blocking_time = mod.max_blocking_time;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const HistoryKeepLastModifier &mod)
    {
        qos.history.kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
        qos.history.depth = mod.depth;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const DurabilityQosModifier &mod)
    {
        qos.durability.kind = mod.kind;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const DataRepresentationModifier &mod)
    {
        qos.representation.value = mod.value;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const ReliabilityQosModifier &mod)
    {
        qos.reliability.kind = mod.kind;
        qos.reliability.max_blocking_time = mod.max_blocking_time;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const HistoryKeepLastModifier &mod)
    {
        qos.history.kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
        qos.history.depth = mod.depth;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const DurabilityQosModifier &mod)
    {
        qos.durability.kind = mod.kind;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const DataRepresentationModifier &mod)
    {
        qos.representation.value = mod.value;
        return qos;
    }

    // -------------------------------------------------------------------------
    // Extended QoS modifiers — required for RTI / Cyclone PSM compatibility
    // -------------------------------------------------------------------------

    struct HistoryKeepAllModifier {};

    struct DeadlineModifier
    {
        rtps::Duration_t period;
    };

    struct LivelinessModifier
    {
        LivelinessQosPolicyKind kind;
        rtps::Duration_t lease_duration;
    };

    struct OwnershipModifier
    {
        OwnershipQosPolicyKind kind;
    };

    struct OwnershipStrengthModifier
    {
        int32_t value;
    };

    struct PartitionModifier
    {
        std::vector<std::string> names;
    };

    struct LifespanModifier
    {
        rtps::Duration_t duration;
    };

    struct ResourceLimitsModifier
    {
        int32_t max_samples;
        int32_t max_instances;
        int32_t max_samples_per_instance;
    };

    inline HistoryKeepAllModifier HistoryKeepAll()
    {
        return {};
    }

    inline DeadlineModifier Deadline(rtps::Duration_t period)
    {
        return DeadlineModifier{period};
    }

    inline LivelinessModifier Liveliness(
        LivelinessQosPolicyKind kind,
        rtps::Duration_t lease = rtps::Time_t::TIME_INFINITE())
    {
        return LivelinessModifier{kind, lease};
    }

    inline OwnershipModifier Ownership(OwnershipQosPolicyKind kind)
    {
        return OwnershipModifier{kind};
    }

    inline OwnershipStrengthModifier OwnershipStrength(int32_t v)
    {
        return OwnershipStrengthModifier{v};
    }

    inline PartitionModifier Partition(std::vector<std::string> names)
    {
        return PartitionModifier{std::move(names)};
    }

    inline LifespanModifier Lifespan(rtps::Duration_t duration)
    {
        return LifespanModifier{duration};
    }

    inline ResourceLimitsModifier ResourceLimits(int32_t max_samples,
                                                 int32_t max_instances = -1,
                                                 int32_t max_samples_per_instance = -1)
    {
        return ResourceLimitsModifier{max_samples, max_instances, max_samples_per_instance};
    }

    // DataWriterQos extended operators
    inline DataWriterQos operator<<(DataWriterQos qos, const HistoryKeepAllModifier&)
    {
        qos.history.kind = HistoryQosPolicyKind::KEEP_ALL_HISTORY_QOS;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const DeadlineModifier& m)
    {
        qos.deadline.period = m.period;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const LivelinessModifier& m)
    {
        qos.liveliness.kind = m.kind;
        qos.liveliness.lease_duration = m.lease_duration;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const OwnershipModifier& m)
    {
        qos.ownership.kind = m.kind;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const OwnershipStrengthModifier& m)
    {
        qos.ownership_strength.value = m.value;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const LifespanModifier& m)
    {
        qos.lifespan.duration = m.duration;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const ResourceLimitsModifier& m)
    {
        qos.resource_limits.max_samples = m.max_samples;
        qos.resource_limits.max_instances = m.max_instances;
        qos.resource_limits.max_samples_per_instance = m.max_samples_per_instance;
        return qos;
    }

    // DataReaderQos extended operators
    inline DataReaderQos operator<<(DataReaderQos qos, const HistoryKeepAllModifier&)
    {
        qos.history.kind = HistoryQosPolicyKind::KEEP_ALL_HISTORY_QOS;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const DeadlineModifier& m)
    {
        qos.deadline.period = m.period;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const LivelinessModifier& m)
    {
        qos.liveliness.kind = m.kind;
        qos.liveliness.lease_duration = m.lease_duration;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const OwnershipModifier& m)
    {
        qos.ownership.kind = m.kind;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const ResourceLimitsModifier& m)
    {
        qos.resource_limits.max_samples = m.max_samples;
        qos.resource_limits.max_instances = m.max_instances;
        qos.resource_limits.max_samples_per_instance = m.max_samples_per_instance;
        return qos;
    }

    // PublisherQos / SubscriberQos — Partition applies at this level
    inline PublisherQos operator<<(PublisherQos qos, const PartitionModifier& m)
    {
        qos.partition.name = m.names;
        return qos;
    }

    inline SubscriberQos operator<<(SubscriberQos qos, const PartitionModifier& m)
    {
        qos.partition.name = m.names;
        return qos;
    }

    // -------------------------------------------------------------------------
    // Remaining standard QoS modifiers
    // -------------------------------------------------------------------------

    struct LatencyBudgetModifier
    {
        rtps::Duration_t duration;
    };

    struct TimeBasedFilterModifier
    {
        rtps::Duration_t minimum_separation;
    };

    struct DestinationOrderModifier
    {
        DestinationOrderQosPolicyKind kind;
    };

    struct WriterDataLifecycleModifier
    {
        bool autodispose_unregistered_instances;
    };

    struct ReaderDataLifecycleModifier
    {
        rtps::Duration_t autopurge_nowriter_samples_delay;
        rtps::Duration_t autopurge_disposed_samples_delay;
    };

    struct PresentationModifier
    {
        PresentationQosPolicyAccessScopeKind access_scope;
        bool coherent_access;
        bool ordered_access;
    };

    struct UserDataModifier
    {
        std::vector<uint8_t> value;
    };

    struct GroupDataModifier
    {
        std::vector<uint8_t> value;
    };

    inline LatencyBudgetModifier LatencyBudget(rtps::Duration_t duration)
    {
        return LatencyBudgetModifier{duration};
    }

    inline TimeBasedFilterModifier TimeBasedFilter(rtps::Duration_t minimum_separation)
    {
        return TimeBasedFilterModifier{minimum_separation};
    }

    inline DestinationOrderModifier DestinationOrder(DestinationOrderQosPolicyKind kind)
    {
        return DestinationOrderModifier{kind};
    }

    inline WriterDataLifecycleModifier WriterDataLifecycle(bool autodispose)
    {
        return WriterDataLifecycleModifier{autodispose};
    }

    inline ReaderDataLifecycleModifier ReaderDataLifecycle(
        rtps::Duration_t nowriter_delay = rtps::Time_t::TIME_INFINITE(),
        rtps::Duration_t disposed_delay = rtps::Time_t::TIME_INFINITE())
    {
        return ReaderDataLifecycleModifier{nowriter_delay, disposed_delay};
    }

    inline PresentationModifier Presentation(
        PresentationQosPolicyAccessScopeKind access_scope,
        bool coherent_access = false,
        bool ordered_access = false)
    {
        return PresentationModifier{access_scope, coherent_access, ordered_access};
    }

    inline UserDataModifier UserData(std::vector<uint8_t> value)
    {
        return UserDataModifier{std::move(value)};
    }

    inline GroupDataModifier GroupData(std::vector<uint8_t> value)
    {
        return GroupDataModifier{std::move(value)};
    }

    // DataWriterQos operators
    inline DataWriterQos operator<<(DataWriterQos qos, const LatencyBudgetModifier& m)
    {
        qos.latency_budget.duration = m.duration;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const DestinationOrderModifier& m)
    {
        qos.destination_order.kind = m.kind;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const WriterDataLifecycleModifier& m)
    {
        qos.writer_data_lifecycle.autodispose_unregistered_instances = m.autodispose_unregistered_instances;
        return qos;
    }

    inline DataWriterQos operator<<(DataWriterQos qos, const UserDataModifier& m)
    {
        qos.user_data.value = m.value;
        return qos;
    }

    // DataReaderQos operators
    inline DataReaderQos operator<<(DataReaderQos qos, const LatencyBudgetModifier& m)
    {
        qos.latency_budget.duration = m.duration;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const TimeBasedFilterModifier& m)
    {
        qos.time_based_filter.minimum_separation = m.minimum_separation;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const DestinationOrderModifier& m)
    {
        qos.destination_order.kind = m.kind;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const ReaderDataLifecycleModifier& m)
    {
        qos.reader_data_lifecycle.autopurge_nowriter_samples_delay = m.autopurge_nowriter_samples_delay;
        qos.reader_data_lifecycle.autopurge_disposed_samples_delay = m.autopurge_disposed_samples_delay;
        return qos;
    }

    inline DataReaderQos operator<<(DataReaderQos qos, const UserDataModifier& m)
    {
        qos.user_data.value = m.value;
        return qos;
    }

    // PublisherQos / SubscriberQos — Presentation and GroupData at this level
    inline PublisherQos operator<<(PublisherQos qos, const PresentationModifier& m)
    {
        qos.presentation.access_scope = m.access_scope;
        qos.presentation.coherent_access = m.coherent_access;
        qos.presentation.ordered_access = m.ordered_access;
        return qos;
    }

    inline PublisherQos operator<<(PublisherQos qos, const GroupDataModifier& m)
    {
        qos.group_data.value = m.value;
        return qos;
    }

    inline SubscriberQos operator<<(SubscriberQos qos, const PresentationModifier& m)
    {
        qos.presentation.access_scope = m.access_scope;
        qos.presentation.coherent_access = m.coherent_access;
        qos.presentation.ordered_access = m.ordered_access;
        return qos;
    }

    inline SubscriberQos operator<<(SubscriberQos qos, const GroupDataModifier& m)
    {
        qos.group_data.value = m.value;
        return qos;
    }

    // QoS builder pattern helpers
    class TopicQosBuilder
    {
    public:
        TopicQosBuilder &reliability(ReliabilityQosPolicyKind kind)
        {
            qos_.reliability.kind = kind;
            return *this;
        }

        TopicQosBuilder &durability(DurabilityQosPolicyKind kind)
        {
            qos_.durability.kind = kind;
            return *this;
        }

        TopicQosBuilder &history(HistoryQosPolicyKind kind, int32_t depth = 1)
        {
            qos_.history.kind = kind;
            qos_.history.depth = depth;
            return *this;
        }

        TopicQos build() const { return qos_; }

    private:
        TopicQos qos_;
    };

} // namespace astutedds::dcps

#endif // ASTUTEDDS_DCPS_QOS_HPP