1 #pragma once
2
3 #include <sdbusplus/async.hpp>
4
5 #include <functional>
6 #include <optional>
7
8 /**
9 * @brief Asynchronously executes a shell command.
10 * @param ctx Async context for monitoring the pipe.
11 * @param cmd Shell command to execute.
12 * @return Task resolving to true on success (exit code 0), false otherwise.
13 */
14 sdbusplus::async::task<bool> asyncSystem(
15 sdbusplus::async::context& ctx, const std::string& cmd,
16 std::optional<std::reference_wrapper<std::string>> result = std::nullopt);
17
18 /**
19 * @brief Convert bytes to an integer of the given type.
20 *
21 * @tparam IntegerType Output integer type (e.g., uint16_t, uint32_t).
22 * @tparam Container A container of uint8_t bytes.
23 * @param data Byte data to convert.
24 * @param bigEndian Set true for big-endian order; false for little-endian.
25 * @return Converted integer.
26 */
27 template <typename IntegerType, typename Container>
28 IntegerType bytesToInt(const Container& data, bool bigEndian = false)
29 {
30 static_assert(std::is_integral_v<IntegerType>,
31 "IntegerType must be an integral type");
32 static_assert(std::is_same_v<typename Container::value_type, uint8_t>,
33 "Container must hold uint8_t elements");
34
35 constexpr size_t maxBytes = sizeof(IntegerType);
36 size_t size = std::min(data.size(), maxBytes);
37
38 IntegerType result = 0;
39 for (size_t i = 0; i < size; ++i)
40 {
41 size_t shift = bigEndian ? (size - 1 - i) * 8 : i * 8;
42 result |= static_cast<IntegerType>(data[i]) << shift;
43 }
44
45 return result;
46 }
47
48 template <typename>
49 inline constexpr bool always_false = false;
50
51 /**
52 * @brief Constructs a vector of bytes (`std::vector<uint8_t>`) from a variable
53 * number of arguments, which can include enums, integral values,
54 * and initializer lists.
55 *
56 * This function is useful when building byte packets or command sequences
57 * to be sent over communication protocols (e.g., I2C, UART, SPI).
58 *
59 * @tparam Args Types of arguments to convert into bytes
60 * @param args The values to encode into the byte vector
61 * @return std::vector<uint8_t> A flattened list of bytes
62 *
63 * @note Passing unsupported types will trigger a compile-time static_assert.
64 * @note Endianness: Multi-byte integers use little-endian order.
65 *
66 * @code
67 * enum class Command : uint8_t { Start = 0x01 };
68 * auto buf = buildByteVector(Command::Start, 0x1234, {0xAA, 0xBB});
69 * // Result: { 0x01, 0x34, 0x12, 0xAA, 0xBB }
70 * @endcode
71 */
72 template <typename... Args>
buildByteVector(Args &&...args)73 std::vector<uint8_t> buildByteVector(Args&&... args)
74 {
75 std::vector<uint8_t> buf;
76
77 auto append = [&](auto&& value) {
78 using T = std::decay_t<decltype(value)>;
79
80 if constexpr (std::is_enum_v<T>)
81 {
82 buf.push_back(static_cast<uint8_t>(value));
83 }
84 else if constexpr (std::is_integral_v<T>)
85 {
86 for (size_t i = 0; i < sizeof(T); ++i)
87 {
88 buf.push_back(static_cast<uint8_t>(value >> (i * 8)));
89 }
90 }
91 else if constexpr (std::is_same_v<T, std::initializer_list<uint8_t>>)
92 {
93 buf.insert(buf.end(), value.begin(), value.end());
94 }
95 else
96 {
97 static_assert(always_false<T>,
98 "Unsupported type in buildByteVector");
99 }
100 };
101
102 (append(std::forward<Args>(args)), ...);
103
104 return buf;
105 }
106