|
morph 0.1.0
Asynchronous bridge between GUI thread and business models
|
Opt-in, compiler-independent shape tag for a type with a custom Glaze codec. More...
#include <concepts>#include <string_view>Go to the source code of this file.
Classes | |
| struct | morph::model::PayloadShapeTag< T > |
| Declares a stable shape tag for a type T whose JSON shape payloadShape cannot decompose. More... | |
Concepts | |
| concept | morph::model::HasPayloadShapeTag |
| Satisfied when T declares a stable shape tag. | |
| concept | morph::model::HasPayloadShapeInner |
| Satisfied when T's tag also names an inner type to render inside it (a transparent wrapper). | |
Opt-in, compiler-independent shape tag for a type with a custom Glaze codec.
morph::model::payloadShape decomposes a payload struct from std:: type traits and Glaze's reflected key strings, never from a compiler-spelled type name — that portability is the whole reason a journal written by one build is readable by another. The cost is that a type carrying its own glz::meta has no reflected members to decompose, so it renders as the single opaque tag x, and a retype between two such types (Rational for Timestamp, Quantity<Gram> for Quantity<Litre>) changes nothing about the fingerprint. For Quantity that is the only place such a swap could be caught at all: neither the unit nor the declared precision travels on the wire, so the JSON is byte-identical either way.
This header is the seam that closes it. A custom-codec type specialises PayloadShapeTag to declare a short, stable, author-written name, and payloadShape renders that name instead of the bare x. The name is spelled in this repository's own sources, so it does not vary with the compiler, the standard library, or the platform — which a glz::name_v tag would, and a journal readable only by the compiler that wrote it is the worse failure.
It is opt-in, and therefore incomplete by construction: a new custom-codec type that declares nothing still renders as x. That is the residual boundary, and docs/spec/journal/journal.md's "What the fingerprint does not catch" states it.
The trait lives in its own header, separate from core/payload_schema.hpp, so that morph/util/rational.hpp and its peers can declare their tags without any of them depending on the journal machinery.
Visibility rule. A specialisation must be visible wherever payloadShape is instantiated for that type, or two translation units would render the same payload differently. In practice this is automatic: a payload struct with a Rational member is only a complete type where morph/util/rational.hpp has been included, and that header carries the specialisation.
Definition in file payload_shape_tag.hpp.