9#include <unordered_set>
21std::string hex_string(std::uint32_t mask)
23 return std::format(
"0x{:X}", mask);
33bool is_contiguous(std::uint32_t mask)
35 return std::popcount(mask) == std::bit_width(mask) - std::countr_zero(mask);
44 .max_value = max_value,
47 .field_display_name = std::move(field_display_name)};
54 "Schema::create requires a 1-byte, 2-byte, or 4-byte attribute size");
56 std::unordered_set<std::string> seen_names;
57 std::optional<std::size_t> layer_type_index;
59 for (std::size_t i = 0; i <
fields.size(); ++i) {
61 const std::uint32_t mask = field.
mask();
63 if (seen_names.contains(field.
name())) {
75 "Field '{}' starts with '{}', which is reserved for the attributes.csv role pin columns. Choose a "
76 "field name outside that namespace.",
83 "Field '{}' has a zero mask: a field must occupy at least one bit.",
87 if (!is_contiguous(mask)) {
89 "Field '{}' has mask '{}': a field mask must be a single contiguous run of bits.",
94 if (
static_cast<std::size_t
>(std::bit_width(mask)) >
attribute_bytes * 8) {
96 "Field '{}' has mask '{}', which extends beyond the '{}'-byte metatile attribute size.",
104 "Field '{}' has default value '{}', which does not fit in its {}-bit mask '{}'.",
114 if (layer_type_index.has_value()) {
116 "Field '{}' carries the layer_type role, but field '{}' already carries it. Only one field may "
117 "pack the layer type.",
123 "Field '{}' carries the layer_type role, so it cannot have a value provider: its values are "
124 "managed by Porytiles.",
129 "Field '{}' carries the layer_type role, so it cannot have a default value: its values are "
130 "managed by Porytiles.",
133 layer_type_index = i;
136 for (std::size_t j = 0; j < i; ++j) {
138 if ((prior.
mask() & mask) != 0) {
140 "Field '{}' has mask '{}', which overlaps mask '{}' of field '{}'.",
148 seen_names.insert(field.
name());
A result type that maintains a chainable sequence of errors for debugging and error reporting.
One named bit-field within a metatile attribute layout.
const std::string & name() const
std::uint32_t default_value() const
bool packs_layer_type() const
Reports whether this field carries the layer_type role.
std::uint32_t width() const
Returns the number of bits the field occupies.
bool has_provider() const
std::uint32_t mask() const
std::uint32_t max_value() const
Returns the largest value the field can hold.
A validated metatile attribute layout: an ordered set of non-overlapping fields.
static ChainableResult< Schema > create(std::vector< Field > fields, std::size_t attribute_bytes)
Validates a set of fields against an attribute size and builds a Schema.
const std::vector< Field > & fields() const
std::size_t attribute_bytes() const
static const Style bold
Bold text formatting.
bool is_pin_column_name(const std::string &name)
Reports whether a column name sits in the reserved pin namespace.
void assert_or_panic(bool condition, const StringViewSourceLoc &s)
Conditionally panics if the given condition is false.
constexpr std::string_view pin_column_prefix
The reserved prefix marking an attributes.csv header column as a role pin column.
The self-contained description a header enum provider needs to scan and validate values.
std::unordered_set< std::string > skipped
EnumDefinition to_enum_definition(std::string field_display_name, std::uint32_t max_value) const
Builds the resolvable enum definition a header provider needs from this description.