blob: 40ce1da4c9650e15070a464d81288a9e6c2bc3f1 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_DBUS_UTILS_SIGNATURE_H_
#define COMPONENTS_DBUS_UTILS_SIGNATURE_H_
#include <dbus/dbus.h>
#include <array>
#include <cstddef>
#include <string>
#include <utility>
#include "base/containers/span.h"
#include "base/files/scoped_file.h"
#include "components/dbus/utils/types.h"
#include "dbus/object_path.h"
namespace dbus_utils {
class Variant;
namespace internal {
template <typename T>
struct DBusSignature {
static_assert(false, "Unsupported type for D-Bus");
};
#define DEFINE_SIMPLE_SIGNATURE(type, signature) \
template <> \
struct DBusSignature<type> { \
static constexpr auto kValue = std::to_array(signature); \
};
DEFINE_SIMPLE_SIGNATURE(int16_t, DBUS_TYPE_INT16_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(uint16_t, DBUS_TYPE_UINT16_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(int32_t, DBUS_TYPE_INT32_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(uint32_t, DBUS_TYPE_UINT32_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(int64_t, DBUS_TYPE_INT64_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(uint64_t, DBUS_TYPE_UINT64_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(bool, DBUS_TYPE_BOOLEAN_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(double, DBUS_TYPE_DOUBLE_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(uint8_t, DBUS_TYPE_BYTE_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(std::string, DBUS_TYPE_STRING_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(dbus::ObjectPath, DBUS_TYPE_OBJECT_PATH_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(Variant, DBUS_TYPE_VARIANT_AS_STRING)
DEFINE_SIMPLE_SIGNATURE(base::ScopedFD, DBUS_TYPE_UNIX_FD_AS_STRING)
#undef DEFINE_SIMPLE_SIGNATURE
// StrJoin takes char[N]s and std::array<char, M>s, each of which is null
// terminated string, and returns the std::array<char, ...> which is the
// result of concat, also null terminated.
template <typename T>
struct IsStrJoinable : std::false_type {};
template <size_t N>
struct IsStrJoinable<char[N]> : std::true_type {};
template <size_t N>
struct IsStrJoinable<std::array<char, N>> : std::true_type {};
template <typename... Ts>
constexpr auto StrJoin(Ts&&... args) {
static_assert((IsStrJoinable<std::remove_cvref_t<Ts>>::value && ...),
"All types passed to StrJoin must be either char[N] or "
"std::array<char, N>.");
constexpr size_t kSize =
(std::size(std::remove_cvref_t<Ts>{}) + ...) - sizeof...(args) + 1;
std::array<char, kSize> result = {};
size_t i = 0;
for (auto span : {base::span<const char>(args)...}) {
for (size_t j = 0; j < span.size(); ++j) {
result[i + j] = span[j];
}
i += span.size() - 1; // Excluding trailing '\0'.
}
return result;
}
template <>
constexpr auto StrJoin() {
return std::array<char, 1>{0};
}
template <typename T>
requires IsSupportedArray<T>::value
struct DBusSignature<T> {
static constexpr auto kValue =
StrJoin(DBUS_TYPE_ARRAY_AS_STRING,
DBusSignature<typename T::value_type>::kValue);
};
template <typename T>
requires IsSupportedMap<T>::value
struct DBusSignature<T> {
using KeyType = typename T::key_type;
using ValueType = typename T::mapped_type;
static constexpr auto kValue = StrJoin(DBUS_TYPE_ARRAY_AS_STRING,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING,
DBusSignature<KeyType>::kValue,
DBusSignature<ValueType>::kValue,
DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
};
template <typename... Ts>
requires IsSupportedStruct<std::tuple<Ts...>>::value
struct DBusSignature<std::tuple<Ts...>> {
static constexpr auto kValue = StrJoin(DBUS_STRUCT_BEGIN_CHAR_AS_STRING,
StrJoin(DBusSignature<Ts>::kValue...),
DBUS_STRUCT_END_CHAR_AS_STRING);
};
template <typename T>
constexpr const char* GetDBusTypeSignature() {
return DBusSignature<T>::kValue.data();
}
template <size_t N>
struct StringLiteral {
// NOLINTNEXTLINE(google-explicit-constructor)
constexpr StringLiteral(const char (&str)[N]) {
std::copy_n(str, N, value.data());
}
std::array<char, N> value;
};
} // namespace internal
} // namespace dbus_utils
#endif // COMPONENTS_DBUS_UTILS_SIGNATURE_H_