|
| 1 | +#ifndef RFL_CONCEPTS_HPP_ |
| 2 | +#define RFL_CONCEPTS_HPP_ |
| 3 | + |
| 4 | +#include <concepts> |
| 5 | +#include <type_traits> |
| 6 | +#include <cstdint> |
| 7 | +#include <cstddef> |
| 8 | +#include <iterator> |
| 9 | + |
| 10 | +namespace rfl { |
| 11 | + |
| 12 | +/// @brief Concept for byte-like types that can be used in contiguous containers |
| 13 | +/// Includes char, signed char, unsigned char, std::byte, and uint8_t |
| 14 | +template<typename T> |
| 15 | +concept ByteLike = std::same_as<T, char> || |
| 16 | + std::same_as<T, signed char> || |
| 17 | + std::same_as<T, unsigned char> || |
| 18 | + std::same_as<T, std::uint8_t> || |
| 19 | + std::same_as<T, std::byte>; |
| 20 | + |
| 21 | +/// @brief Concept for containers with a contiguous sequence of byte-like types |
| 22 | +/// Requires: |
| 23 | +/// - Container has a value_type that is byte-like |
| 24 | +/// - Container provides data() method returning a pointer to contiguous memory |
| 25 | +/// - Container provides size() method returning the number of elements |
| 26 | +/// - Container supports range-based for loops (begin/end) |
| 27 | +template<typename Container> |
| 28 | +concept ContiguousByteContainer = requires(const Container& c) { |
| 29 | + typename Container::value_type; |
| 30 | + { c.data() } -> std::convertible_to<const typename Container::value_type*>; |
| 31 | + { c.size() } -> std::convertible_to<std::size_t>; |
| 32 | + { c.begin() } -> std::input_iterator; |
| 33 | + { c.end() } -> std::input_iterator; |
| 34 | + requires ByteLike<typename Container::value_type>; |
| 35 | + requires std::contiguous_iterator<decltype(c.begin())>; |
| 36 | +}; |
| 37 | + |
| 38 | +/// @brief Concept for mutable containers with a contiguous sequence of byte-like types |
| 39 | +/// Extends ContiguousByteContainer with mutable access requirements |
| 40 | +template<typename Container> |
| 41 | +concept MutableContiguousByteContainer = ContiguousByteContainer<Container> && requires(Container& c) { |
| 42 | + { c.data() } -> std::convertible_to<typename Container::value_type*>; |
| 43 | + { c.begin() } -> std::output_iterator<typename Container::value_type>; |
| 44 | + { c.end() } -> std::output_iterator<typename Container::value_type>; |
| 45 | +}; |
| 46 | + |
| 47 | +/// @brief Concept for back-insertable byte containers (like std::vector<uint8_t>) |
| 48 | +/// Useful for containers that can grow dynamically during serialization |
| 49 | +template<typename Container> |
| 50 | +concept BackInsertableByteContainer = ContiguousByteContainer<Container> && requires(Container& c, typename Container::value_type v) { |
| 51 | + c.push_back(v); |
| 52 | + c.reserve(std::size_t{}); |
| 53 | + { c.capacity() } -> std::convertible_to<std::size_t>; |
| 54 | +}; |
| 55 | + |
| 56 | +/// @brief Concept for byte spans or views (read-only, non-owning containers) |
| 57 | +/// Includes std::span<const uint8_t>, std::string_view when used with char data, etc. |
| 58 | +template<typename Container> |
| 59 | +concept ByteSpanLike = ContiguousByteContainer<Container> && |
| 60 | + std::is_trivially_copyable_v<Container> && |
| 61 | + std::is_trivially_destructible_v<Container>; |
| 62 | + |
| 63 | +} // namespace rfl |
| 64 | + |
| 65 | +#endif // RFL_CONCEPTS_HPP_ |
0 commit comments