Astarte device API for C++ 0.8.1
Astarte device SDK for C++
Loading...
Searching...
No Matches
data.hpp
Go to the documentation of this file.
1// (C) Copyright 2025, SECO Mind Srl
2//
3// SPDX-License-Identifier: Apache-2.0
4
5#ifndef ASTARTE_DEVICE_SDK_DATA_H
6#define ASTARTE_DEVICE_SDK_DATA_H
7
15
16#include <chrono>
17#include <cstdint>
18#include <optional>
19#include <ostream>
20#include <string>
21#include <string_view>
22#include <type_traits>
23#include <variant>
24#include <vector>
25
28
29namespace astarte::device {
30
37template <typename T>
38concept DataAllowedType = requires {
39 requires std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> || std::is_same_v<T, double> ||
40 std::is_same_v<T, bool> || std::is_same_v<T, std::string> ||
41 std::is_same_v<T, std::string_view> || std::is_same_v<T, std::vector<uint8_t>> ||
42 std::is_same_v<T, std::chrono::system_clock::time_point> ||
43 std::is_same_v<T, std::vector<int32_t>> || std::is_same_v<T, std::vector<int64_t>> ||
44 std::is_same_v<T, std::vector<double>> || std::is_same_v<T, std::vector<bool>> ||
45 std::is_same_v<T, std::vector<std::string>> ||
46 std::is_same_v<T, std::vector<std::vector<uint8_t>>> ||
47 std::is_same_v<T, std::vector<std::chrono::system_clock::time_point>>;
48};
49
61class Data {
62 public:
73 template <DataAllowedType T>
74 explicit Data(const T& value) {
75 if constexpr (std::is_same_v<T, std::string_view>) {
76 data_ = std::string(value);
77 } else {
78 data_ = value;
79 }
80 }
81
93 template <DataAllowedType T>
94 [[nodiscard]] auto into() const
95 -> std::conditional_t<std::is_same_v<T, std::string_view>, std::string_view, const T&> {
96 if constexpr (std::is_same_v<T, std::string_view>) {
97 return std::string_view(std::get<std::string>(data_));
98 } else {
99 return std::get<T>(data_);
100 }
101 }
102
113 template <DataAllowedType T>
114 [[nodiscard]] auto try_into() const -> std::optional<T> {
115 if constexpr (std::is_same_v<T, std::string_view>) {
116 if (std::holds_alternative<std::string>(data_)) {
117 return std::string_view(std::get<std::string>(data_));
118 }
119 } else {
120 if (std::holds_alternative<T>(data_)) {
121 return std::get<T>(data_);
122 }
123 }
124
125 return std::nullopt;
126 }
127
132 [[nodiscard]] auto get_type() const -> Type;
133
138 [[nodiscard]] auto get_raw_data() const
139 -> const std::variant<int32_t, int64_t, double, bool, std::string, std::vector<uint8_t>,
140 std::chrono::system_clock::time_point, std::vector<int32_t>,
141 std::vector<int64_t>, std::vector<double>, std::vector<bool>,
142 std::vector<std::string>, std::vector<std::vector<uint8_t>>,
143 std::vector<std::chrono::system_clock::time_point>>&;
149 [[nodiscard]] auto operator==(const Data& other) const -> bool;
150
156 [[nodiscard]] auto operator!=(const Data& other) const -> bool;
157
158 private:
159 std::variant<int32_t, int64_t, double, bool, std::string, std::vector<uint8_t>,
160 std::chrono::system_clock::time_point, std::vector<int32_t>, std::vector<int64_t>,
161 std::vector<double>, std::vector<bool>, std::vector<std::string>,
162 std::vector<std::vector<uint8_t>>,
163 std::vector<std::chrono::system_clock::time_point>>
164 data_;
165};
166
167} // namespace astarte::device
168
170template <>
177 template <typename ParseContext>
178 constexpr auto parse(ParseContext& ctx) const {
179 return ctx.begin();
180 }
181
188 template <typename FormatContext>
189 // NOLINTNEXTLINE(readability-function-size)
190 auto format(const astarte::device::Data& data, FormatContext& ctx) const {
191 auto out = ctx.out();
192
193 if (std::holds_alternative<int32_t>(data.get_raw_data())) {
194 out = astarte_fmt::format_to(out, "{}", std::get<int32_t>(data.get_raw_data()));
195 } else if (std::holds_alternative<int64_t>(data.get_raw_data())) {
196 out = astarte_fmt::format_to(out, "{}", std::get<int64_t>(data.get_raw_data()));
197 } else if (std::holds_alternative<double>(data.get_raw_data())) {
198 out = astarte_fmt::format_to(out, "{}", std::get<double>(data.get_raw_data()));
199 } else if (std::holds_alternative<bool>(data.get_raw_data())) {
200 const auto* bool_str = (std::get<bool>(data.get_raw_data()) ? "true" : "false");
201 out = astarte_fmt::format_to(out, "{}", bool_str);
202 } else if (std::holds_alternative<std::string>(data.get_raw_data())) {
203 out = astarte_fmt::format_to(out, R"("{}")", std::get<std::string>(data.get_raw_data()));
204 } else if (std::holds_alternative<std::vector<uint8_t>>(data.get_raw_data())) {
206 std::get<std::vector<uint8_t>>(data.get_raw_data()));
207 } else if (std::holds_alternative<std::chrono::system_clock::time_point>(data.get_raw_data())) {
209 out, std::get<std::chrono::system_clock::time_point>(data.get_raw_data()));
210 } else if (std::holds_alternative<std::vector<int32_t>>(data.get_raw_data())) {
212 std::get<std::vector<int32_t>>(data.get_raw_data()));
213 } else if (std::holds_alternative<std::vector<int64_t>>(data.get_raw_data())) {
215 std::get<std::vector<int64_t>>(data.get_raw_data()));
216 } else if (std::holds_alternative<std::vector<double>>(data.get_raw_data())) {
218 std::get<std::vector<double>>(data.get_raw_data()));
219 } else if (std::holds_alternative<std::vector<bool>>(data.get_raw_data())) {
220 astarte::device::utils::format_vector(out, std::get<std::vector<bool>>(data.get_raw_data()));
221 } else if (std::holds_alternative<std::vector<std::string>>(data.get_raw_data())) {
223 out, std::get<std::vector<std::string>>(data.get_raw_data()));
224 } else if (std::holds_alternative<std::vector<std::vector<uint8_t>>>(data.get_raw_data())) {
226 out, std::get<std::vector<std::vector<uint8_t>>>(data.get_raw_data()));
227 } else if (std::holds_alternative<std::vector<std::chrono::system_clock::time_point>>(
228 data.get_raw_data())) {
230 out, std::get<std::vector<std::chrono::system_clock::time_point>>(data.get_raw_data()));
231 }
232
233 return out;
234 }
235};
236
243inline auto operator<<(std::ostream& out, const astarte::device::Data& data) -> std::ostream& {
244 out << astarte_fmt::format("{}", data);
245 return out;
246}
247
248#endif // ASTARTE_DEVICE_SDK_DATA_H
Represents a single Astarte data value.
Definition data.hpp:61
auto get_raw_data() const -> const std::variant< int32_t, int64_t, double, bool, std::string, std::vector< uint8_t >, std::chrono::system_clock::time_point, std::vector< int32_t >, std::vector< int64_t >, std::vector< double >, std::vector< bool >, std::vector< std::string >, std::vector< std::vector< uint8_t > >, std::vector< std::chrono::system_clock::time_point > > &
Returns the raw data variant contained in this class instance.
auto try_into() const -> std::optional< T >
Attempts to convert the Astarte data class to the specified type T safely.
Definition data.hpp:114
Data(const T &value)
Constructs a Data object from a value of any DataAllowedType.
Definition data.hpp:74
auto into() const -> std::conditional_t< std::is_same_v< T, std::string_view >, std::string_view, const T & >
Converts the Astarte data class to the specified type T.
Definition data.hpp:94
auto get_type() const -> Type
Gets the type of the data contained in this class instance.
C++ concept to restrict the allowed types for instances of an Astarte data class.
Definition data.hpp:38
auto operator<<(std::ostream &out, const astarte::device::Data &data) -> std::ostream &
Stream insertion operator for Data.
Definition data.hpp:243
Data formatting utilities for Astarte types.
void format_vector(OutputIt &out, const std::vector< T > &data)
Format a generic vector into a comma-separated list in brackets.
Definition formatter.hpp:167
void format_timestamp(OutputIt &out, const std::chrono::system_clock::time_point &data)
Format a timestamp into an ISO 8601 string literal.
Definition formatter.hpp:118
void format_base64(OutputIt &out, const std::vector< uint8_t > &data)
Format a vector of bytes into a Base64 string literal.
Definition formatter.hpp:63
Umbrella namespace for the Astarte device library.
Definition data.hpp:29
Type
Enumeration of supported Astarte data types.
Definition type.hpp:33
Namespace alias for the formatting library (std or fmt).
Definition formatter.hpp:45
Global namespace for all Astarte related functionality.
Definition data.hpp:29
auto format(const astarte::device::Data &data, FormatContext &ctx) const
Formats the Data variant-like object by dispatching to the correct formatter.
Definition data.hpp:190
constexpr auto parse(ParseContext &ctx) const
Parses the format string.
Definition data.hpp:178
Base formatter struct declaration for Doxygen.
Definition formatter.hpp:48
Types definitions for communication with Astarte.