ADR 0036: Readable C++ metadata values¶
Status: Accepted
Date: 2026-09-28
Context¶
The C++ wrapper represented a metadata value as MetadataInput, a move-only
handle to a native input. Reads converted every stored value back into such a
handle. That covered metadata queries, activity and job metadata, and the
parameters of a regeneration plan. The handle could be passed to an exact-value
query or copied to another target, but its value could not be read. The C ABI
has a typed getter for every value kind, and Python returns frozen value
classes, so only C++ hosts were cut off from their own data.
The Kdenlive pilot recorded its render arguments as an ordered list on each proxy activity, and could not read them back. The gap is general. A C++ host cannot use its own data in several situations:
A worker handed a regeneration plan cannot read the parameters it must render with.
An OpenAssetIO manager or asset browser cannot show metadata.
An editor cannot read back an identifier or setting it stored on an asset.
A test cannot compare a value it wrote with the value it reads.
Decision¶
MetadataValue replaces MetadataInput as the one C++ type for writing and
reading metadata, as Python’s value classes already are.
It is a copyable value holding a
std::variantof alternatives:MetadataStringandMetadataLanguageString;MetadataSignedIntegerandMetadataUnsignedInteger;MetadataDecimal, with a base-ten coefficient string and a scale;MetadataBoolean,MetadataTimestamp,MetadataUri, andMetadataBytes;MetadataRational,MetadataList,MetadataStructureofMetadataFields, andMetadataReference.
The factories keep their names:
plainString,languageString,signedInteger,unsignedInteger,decimal,boolean,timestamp,uri,bytes,rational,list,structure, andreference.getIf<T>()returns the alternative or null, andvariant()supportsstd::visit. Values and alternatives compare with==.MetadataAssertion::valueandRegenerationParameter::valueareMetadataValues, andaddMetadataValueandqueryMetadatatake one.A value is converted to a native input, and validated, when an operation consumes it. Invalid text or an invalid decimal is reported by that operation, as before. The value itself no longer carries an error.
Alternatives considered¶
Add read accessors to
MetadataInput. The handle would still be move-only, and every read would call the C ABI again. A plain value is simpler to copy, compare, and keep.Keep a separate read type next to
MetadataInput. Two types for one concept would force a conversion whenever a read value is written again, for example when a regeneration plan’s parameters are copied to a new job.Expose
std::variantdirectly as the value type. A recursive variant needs a wrapper for its list and structure members anyway. A class also keeps the factories and room for later additions.
Standards impact¶
None. The value kinds are unchanged (ADR 0004).
Consequences¶
C++ hosts read every metadata value on every read path. Code that named
MetadataInput or MetadataFieldInput, or called MetadataInput::error(),
must be updated. The C ABI is unchanged.