71#include <Ultralight/detail/FixedString.h>
73#include <Ultralight/dom/data/detail/Accessors.h>
74#include <Ultralight/dom/detail/Support.h>
112inline constexpr size_t kNpos =
static_cast<size_t>(-1);
118void SchemaErrorDuplicateEntryName(
const char* name);
119void SchemaErrorEntryNameNotAnIdentifier(
const char* name);
120void SchemaErrorVarNameMustStartWithDashDash(
const char* name);
121void SchemaErrorVarNameMalformed(
const char* name);
122void SchemaErrorAnnotationTargetNotFound(
const char* name);
123void SchemaErrorAnnotationTargetNotAField(
const char* name);
124void SchemaErrorAnnotationDuplicated(
const char* name);
125void SchemaErrorValidatorDuplicated(
const char* name);
126void SchemaErrorValidatorSignatureMismatch(
const char* name);
127void SchemaErrorValidatorWithoutEditable(
const char* name);
128void SchemaErrorEditableOnNonLeaf(
const char* name);
129void SchemaErrorEditableOnStyleValue(
const char* name);
132inline constexpr bool kAlwaysFalse =
false;
136constexpr bool NamesEqual(
const char* a,
const char* b) {
137 while (*a && *a == *b) {
148constexpr bool IsIdentifierName(std::string_view name) {
151 for (
size_t i = 0; i < name.size(); i++) {
152 const char c = name[i];
153 const bool alpha = (c >=
'A' && c <=
'Z') || (c >=
'a' && c <=
'z') || c ==
'_';
154 if (!alpha && (i == 0 || c <
'0' || c >
'9'))
162constexpr bool IsVarName(std::string_view name) {
163 if (name.size() < 3 || name[0] !=
'-' || name[1] !=
'-')
165 for (
char c : name.substr(2)) {
166 if (!((c >=
'a' && c <=
'z') || (c >=
'0' && c <=
'9') || c ==
'-'))
172consteval void CheckTokenName(
const char* name,
bool is_var) {
173 const std::string_view n(name);
175 if (!IsIdentifierName(n))
176 SchemaErrorEntryNameNotAnIdentifier(name);
177 }
else if (n.size() < 3 || n[0] !=
'-' || n[1] !=
'-') {
178 SchemaErrorVarNameMustStartWithDashDash(name);
179 }
else if (!IsVarName(n)) {
180 SchemaErrorVarNameMalformed(name);
185using ListRow = std::remove_cvref_t<decltype(*std::begin(std::declval<const C&>()))>;
188concept IsIterable =
requires(
const C& c) {
209template <
typename Fn>
219struct EditableEntry {
228struct InternalEntry {
239template <
typename Fn>
240struct ValidateEntry {
275 consteval EditableEntry
operator()(
const char* name)
const {
return { name }; }
303 consteval InternalEntry
operator()(
const char* name)
const {
return { name }; }
366template <
typename Fn>
367 requires std::is_class_v<Fn>
384template <
typename Fn>
385 requires std::is_class_v<Fn>
386consteval ValidateEntry<Fn>
Validate(
const char* name, Fn fn) {
393template <
typename Owner,
typename Value,
typename Accessor,
typename Val
idator = NoVal
idate>
408 static constexpr bool kHasAccessor = !std::is_same_v<Accessor, std::nullptr_t>;
413 static constexpr bool kHasValidator = !std::is_same_v<Validator, NoValidate>;
419template <
typename Owner,
typename Container,
typename Accessor,
typename KeyPtr>
434 static constexpr bool kKeyed = !std::is_same_v<KeyPtr, std::nullptr_t>;
440template <
typename Payload>
451template <
typename Owner,
typename Value,
typename Accessor>
461#if ULTRALIGHT_REFLECTION
467struct ReflectEntry {};
499consteval ReflectEntry<T> Reflect() {
500 static_assert(std::is_aggregate_v<T> && std::is_class_v<T> && !std::is_polymorphic_v<T>,
501 "Reflect<T>() requires a plain aggregate class type");
514#include <Ultralight/dom/data/detail/SchemaImpl.h>
550template <detail::IsAccessor A,
typename... Tags>
551consteval auto Field(
const char* name, A accessor, Tags... tags) {
552 detail::CheckTokenName(name,
false);
553 static_assert((int(detail::IsValidateWith<Tags>::value) + ... + 0) <= 1,
554 "only one Validate(fn) per Field");
555 auto validator = detail::PickValidator(tags...);
557 decltype(validator)> { name, accessor, validator,
558 detail::FieldFlags(tags...) };
576template <
typename Value,
typename... Tags>
577 requires (!detail::IsAccessor<Value>)
578consteval auto Field(
const char* name, Tags... tags) {
579 detail::CheckTokenName(name,
false);
580 static_assert((int(detail::IsValidateWith<Tags>::value) + ... + 0) <= 1,
581 "only one Validate(fn) per Field");
582 auto validator = detail::PickValidator(tags...);
584 name,
nullptr, validator, detail::FieldFlags(tags...)
613template <detail::IsAccessor A,
typename KeyPtr,
typename... Tags>
614 requires std::is_member_object_pointer_v<KeyPtr>
615consteval auto List(
const char* name, A accessor, KeyPtr key, Tags... tags) {
616 detail::CheckTokenName(name,
false);
617 using Container = detail::AccessorValue<A>;
618 static_assert(detail::IsIterable<Container>,
619 "List accessor must return an iterable container of rows");
620 static_assert(std::is_base_of_v<detail::AccessorOwner<KeyPtr>, detail::ListRow<Container>>,
621 "List key must be a member pointer of the row type");
623 name, accessor, key, detail::ListFlags(tags...)
641template <detail::IsAccessor A,
typename... Tags>
642 requires (!std::is_member_object_pointer_v<Tags> && ...)
643consteval auto List(
const char* name, A accessor, Tags... tags) {
644 detail::CheckTokenName(name,
false);
645 using Container = detail::AccessorValue<A>;
646 static_assert(detail::IsIterable<Container>,
647 "List accessor must return an iterable container of rows");
649 name, accessor,
nullptr, detail::ListFlags(tags...)
687template <
typename Payload = void,
typename... Tags>
689 detail::CheckTokenName(name,
false);
724template <detail::IsAccessor A>
725consteval auto Var(
const char* name, A accessor) {
726 detail::CheckTokenName(name,
true);
776template <
typename... Entries>
777consteval auto Schema(Entries... entries) {
778 return detail::BuildSchema(entries...);
A layout node that organizes child nodes into a row or column.
Definition Container.h:101
Unicode string container with conversions for UTF-8, UTF-16, and UTF-32.
Definition String.h:31
A generic value passed to data-binding formatters and handlers.
Definition Value.h:95
Data-binding API that connects native C++ data to HTML and CSS markup.
Definition ActionInfo.h:13
consteval ValidateWith< Fn > Validate(Fn fn)
Attach a validator to a field (a Field() tag).
Definition Schema.h:368
consteval auto Field(const char *name, A accessor, Tags... tags)
Declare a field.
Definition Schema.h:551
constexpr InternalTag Internal
Definition Schema.h:305
consteval ActionToken< Payload > Action(const char *name, Tags... tags)
Declare an action (a request the page sends to your code).
Definition Schema.h:688
constexpr EditableTag Editable
Definition Schema.h:277
consteval auto Schema(Entries... entries)
Declare a type's schema.
Definition Schema.h:777
constexpr OnlyLatestTag OnlyLatest
Definition Schema.h:321
consteval auto Var(const char *name, A accessor)
Declare a CSS custom property that follows your data.
Definition Schema.h:725
EntryFlags
Flags on a schema entry.
Definition Schema.h:99
@ kEntryFlags_Nullable
A nested object that may be absent.
Definition Schema.h:106
@ kEntryFlags_OnlyLatest
Only the newest pending action is delivered.
Definition Schema.h:102
@ kEntryFlags_Keyed
A list whose rows have a key member.
Definition Schema.h:104
@ kEntryFlags_Internal
Pages can't reach this entry (see dd::Internal).
Definition Schema.h:101
@ kEntryFlags_Var
A CSS custom property (see Var()).
Definition Schema.h:105
@ kEntryFlags_Editable
The page may request changes to this field.
Definition Schema.h:100
consteval auto List(const char *name, A accessor, KeyPtr key, Tags... tags)
Declare a keyed list.
Definition Schema.h:615
Direct C++ access to modify page elements and handle events.
Root namespace for every public Ultralight type, function, and enumeration.
An action entry (the value Action() returns).
Definition Schema.h:441
Payload payload_type
The payload type (void for none).
Definition Schema.h:442
const char * name
The action's name.
Definition Schema.h:444
uint8_t flags
The EntryFlags set on this action.
Definition Schema.h:445
Marks a field the page may request changes to.
Definition Schema.h:267
consteval EditableEntry operator()(const char *name) const
Mark an already-declared field as Editable (a Schema() entry).
Definition Schema.h:275
A field entry (the value Field() returns).
Definition Schema.h:394
Value value_type
The field's value type.
Definition Schema.h:396
static constexpr bool kHasValidator
Whether or not a validator is attached with the Field() tag form of Validate().
Definition Schema.h:413
Accessor accessor_type
The accessor's type (std::nullptr_t without one).
Definition Schema.h:397
Owner owner_type
The type the accessor reads from (void without one).
Definition Schema.h:395
const char * name
The field's name.
Definition Schema.h:400
ULTRALIGHT_DOM_NO_UNIQUE_ADDRESS Validator validator
The validator, if any.
Definition Schema.h:402
uint8_t flags
The EntryFlags set on this field.
Definition Schema.h:403
Accessor accessor
Reads the value from a const instance.
Definition Schema.h:401
static constexpr bool kHasAccessor
Whether or not the field has an accessor.
Definition Schema.h:408
Validator validator_type
The type of the validator from Validate(), if any.
Definition Schema.h:398
Marks a field or list that pages can't reach.
Definition Schema.h:295
consteval InternalEntry operator()(const char *name) const
Mark an already-declared field or list as Internal (a Schema() entry).
Definition Schema.h:303
A list entry (the value List() returns).
Definition Schema.h:420
static constexpr bool kKeyed
Whether or not rows have a key (rows are matched by position otherwise).
Definition Schema.h:434
Owner owner_type
The type the accessor reads from.
Definition Schema.h:421
const char * name
The list's name.
Definition Schema.h:426
Container container_type
The container type.
Definition Schema.h:422
KeyPtr key_pointer_type
The key member pointer's type (else std::nullptr_t).
Definition Schema.h:424
uint8_t flags
The EntryFlags set on this list.
Definition Schema.h:429
KeyPtr key
The row member that identifies each row (null without a key).
Definition Schema.h:428
Accessor accessor
Reads the container from a const instance.
Definition Schema.h:427
detail::ListRow< Container > row_type
The row type.
Definition Schema.h:423
Marks an action whose pending emissions collapse into the newest one.
Definition Schema.h:320
A CSS custom property entry (the value Var() returns).
Definition Schema.h:452
Value value_type
The accessor's value type.
Definition Schema.h:454
Accessor accessor_type
The accessor's type.
Definition Schema.h:455
Owner owner_type
The type the accessor reads from.
Definition Schema.h:453
const char * name
The property's name, including the leading two hyphens.
Definition Schema.h:457
Accessor accessor
Reads the value from a const instance.
Definition Schema.h:458