Program Listing for File message.hpp

Return to documentation for file (/tmp/ws/src/myactuator_rmd/include/myactuator_rmd/protocol/message.hpp)

#ifndef MYACTUATOR_RMD__PROTOCOL__MESSAGE
#define MYACTUATOR_RMD__PROTOCOL__MESSAGE
#pragma once

#include <array>
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <type_traits>


namespace myactuator_rmd {

  class Message {
    public:
      [[nodiscard]]
      constexpr std::array<std::uint8_t,8> const& getData() const noexcept;

    protected:
      constexpr Message(std::array<std::uint8_t,8> const& data = {}) noexcept;
      Message(Message const&) = default;
      Message& operator = (Message const&) = default;
      Message(Message&&) = default;
      Message& operator = (Message&&) = default;

      template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
      void setAt(T const val, std::size_t const i);

      template <typename T, typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
      [[nodiscard]]
      T getAs(std::size_t const i) const;

      std::array<std::uint8_t,8> data_;
  };

  constexpr std::array<std::uint8_t,8> const& Message::getData() const noexcept {
    return data_;
  }

  constexpr Message::Message(std::array<std::uint8_t,8> const& data) noexcept
  : data_{data} {
    return;
  }

  template <typename T, typename std::enable_if_t<std::is_integral_v<T>>*>
  void Message::setAt(T const val, std::size_t const i) {
    if (i + sizeof(T)/sizeof(std::uint8_t) > data_.size()) {
      throw std::out_of_range("Requested index out of range!");
    }
    std::memcpy(&data_[i], &val, sizeof(T));
    return;
  }

  template <typename T, typename std::enable_if_t<std::is_integral_v<T>>*>
  T Message::getAs(std::size_t const i) const {
    if (i + sizeof(T)/sizeof(std::uint8_t) > data_.size()) {
      throw std::out_of_range("Requested index out of range!");
    }
    T val {};
    std::memcpy(&val, &data_[i], sizeof(T));
    return val;
  }

}

#endif // MYACTUATOR_RMD__PROTOCOL__MESSAGE