11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
26PROMEKI_NAMESPACE_BEGIN
50enum DataTypeID : uint16_t {
51 DataTypeInvalid = 0x00,
57 DataTypeUInt16 = 0x04,
59 DataTypeUInt32 = 0x06,
61 DataTypeUInt64 = 0x08,
63 DataTypeDouble = 0x0A,
65 DataTypeString = 0x0C,
66 DataTypeBuffer = 0x0D,
67 DataTypeNoValue = 0x0E,
71 DataTypeDateTime = 0x11,
72 DataTypeTimeStamp = 0x12,
73 DataTypeSize2D = 0x13,
74 DataTypeRational = 0x14,
75 DataTypeFrameRate = 0x15,
76 DataTypeTimecode = 0x16,
78 DataTypeColorModel = 0x18,
79 DataTypeMemSpace = 0x19,
80 DataTypePixelMemLayout = 0x1A,
81 DataTypePixelFormat = 0x1B,
83 DataTypeStringList = 0x1D,
91 DataTypeHashMap = 0x23,
92 DataTypeHashSet = 0x24,
95 DataTypeJsonObject = 0x30,
96 DataTypeJsonArray = 0x31,
97 DataTypeXYZColor = 0x32,
98 DataTypeAudioDesc = 0x33,
99 DataTypeImageDesc = 0x34,
100 DataTypeMediaDesc = 0x35,
102 DataTypeEnumList = 0x37,
103 DataTypeMediaTimeStamp = 0x38,
104 DataTypeMacAddress = 0x39,
105 DataTypeEUI64 = 0x3A,
106 DataTypeMediaPipelineStage = 0x3B,
107 DataTypeMediaPipelineRoute = 0x3C,
108 DataTypeMediaPipelineConfig = 0x3D,
109 DataTypeMediaPipelineStats = 0x3E,
110 DataTypeVideoFormat = 0x3F,
113 DataTypeMasteringDisplay = 0x40,
114 DataTypeContentLightLevel = 0x41,
117 DataTypeMediaIODescription = 0x42,
120 DataTypeFrameNumber = 0x43,
121 DataTypeFrameCount = 0x44,
122 DataTypeMediaDuration = 0x45,
124 DataTypeAudioFormat = 0x47,
125 DataTypeMediaPayload = 0x48,
126 DataTypeDuration = 0x49,
127 DataTypeSocketAddress = 0x4A,
128 DataTypeSdpSession = 0x4B,
129 DataTypeVideoCodec = 0x4C,
130 DataTypeAudioCodec = 0x4D,
131 DataTypeAudioChannelMap = 0x4E,
132 DataTypeAudioStreamDesc = 0x4F,
133 DataTypeWindowedStat = 0x50,
134 DataTypeWindowedStatsBundle = 0x51,
135 DataTypeAudioMarkerList = 0x52,
136 DataTypeVariantList = 0x53,
137 DataTypeVariantMap = 0x54,
138 DataTypeXmlDocument = 0x55,
139 DataTypeXmlElement = 0x56,
140 DataTypeSslContext = 0x57,
141 DataTypeAncFormat = 0x58,
142 DataTypeAncPacket = 0x59,
143 DataTypeAncDesc = 0x5A,
144 DataTypeCea708Cdp = 0x5B,
145 DataTypeSubtitle = 0x5C,
146 DataTypeSubtitleSpan = 0x5D,
148 DataTypeCea608 = 0x5F,
149 DataTypeCea708Service = 0x60,
150 DataTypeCea708DtvccPacket = 0x61,
151 DataTypeHdrStaticMetadata = 0x62,
152 DataTypeHdrDynamic2094_40 = 0x63,
155 DataTypeVideoPortRef = 0x64,
156 DataTypeSdiSignalConfig = 0x65,
157 DataTypeHdmiSignalConfig = 0x66,
158 DataTypeVideoReferenceConfig = 0x67,
159 DataTypeSdiOutputFanoutConfig = 0x68,
160 DataTypeSdiVpid = 0x69,
161 DataTypeAncAtc = 0x6A,
162 DataTypeAncAfd = 0x6B,
163 DataTypeAncOp47Sdp = 0x6C,
164 DataTypeSt2020Audio = 0x6D,
165 DataTypeTimecodeUserbits = 0x6E,
166 DataTypeIpv4Address = 0x6F,
167 DataTypeIpv6Address = 0x70,
168 DataTypeNetworkAddress = 0x71,
169 DataTypePixelAspect = 0x72,
170 DataTypeTranscript = 0x73,
171 DataTypeTranscriptWord = 0x74,
172 DataTypeMdnsServiceType = 0x75,
173 DataTypeMdnsTxtRecord = 0x76,
174 DataTypeMdnsServiceInstance = 0x77,
178inline constexpr DataTypeID DataTypeUserBegin =
static_cast<DataTypeID
>(0x4000);
180inline constexpr DataTypeID DataTypeUserEnd =
static_cast<DataTypeID
>(0xFFFF);
196void registerBuiltinDataTypes();
286 void (*defaultConstruct)(
void *p) =
nullptr;
287 void (*copyConstruct)(
void *dst,
const void *src) =
nullptr;
288 void (*moveConstruct)(
void *dst,
void *src) =
nullptr;
289 void (*destroy)(
void *p) =
nullptr;
290 bool (*equal)(
const void *a,
const void *b) =
nullptr;
291 String (*toString)(
const void *p, Error *err) =
nullptr;
292 bool (*fromString)(
const String &s,
void *out, Error *err) =
nullptr;
293 int64_t (*toInt)(
const void *p, Error *err) =
nullptr;
294 bool (*fromInt)(int64_t v,
void *out, Error *err) =
nullptr;
295 double (*toFloat)(
const void *p, Error *err) =
nullptr;
296 bool (*fromFloat)(
double v,
void *out, Error *err) =
nullptr;
297 JsonObject (*toJson)(
const void *p, Error *err) =
nullptr;
298 bool (*fromJson)(
const JsonObject &j,
void *out, Error *err) =
nullptr;
299 void (*writeStream)(DataStream &s,
const void *p) =
nullptr;
300 void (*readStream)(DataStream &s,
void *p) =
nullptr;
311 DataTypeID
id = DataTypeInvalid;
312 const char *name =
"Invalid";
313 uint32_t version = 0;
316 std::type_index cppType = std::type_index(
typeid(
void));
321 DataType() =
default;
324 explicit DataType(
const Data *d) : _data(d) {
return; }
336 DataType(DataTypeID
id);
339 bool isValid()
const {
return _data !=
nullptr; }
342 DataTypeID id()
const {
return _data !=
nullptr ? _data->id : DataTypeInvalid; }
345 const char *name()
const {
return _data !=
nullptr ? _data->name :
"Invalid"; }
348 uint32_t version()
const {
return _data !=
nullptr ? _data->version : 0; }
351 size_t size()
const {
return _data !=
nullptr ? _data->size : 0; }
354 size_t alignment()
const {
return _data !=
nullptr ? _data->align : 1; }
357 std::type_index cppType()
const {
358 return _data !=
nullptr ? _data->cppType : std::type_index(
typeid(
void));
368 const Ops &ops()
const;
371 const Data *data()
const {
return _data; }
374 bool operator==(
const DataType &o)
const {
return _data == o._data; }
375 bool operator!=(
const DataType &o)
const {
return _data != o._data; }
399 static DataType registerType(DataTypeID
id,
const char *name, uint32_t version,
400 std::type_index ti,
size_t size,
size_t align, Ops ops);
403 static List<DataTypeID> registeredIds();
406 static DataType byId(DataTypeID
id);
409 static DataType byName(
const char *name);
428 template <
typename T>
static DataType of();
431 static DataType byCppType(std::type_index ti);
434 const Data *_data =
nullptr;
441concept HasEqualityOp =
requires(
const T &a,
const T &b) {
442 { a == b } -> std::convertible_to<bool>;
446concept HasMemberToString =
requires(
const T &t) {
447 { t.toString() } -> std::convertible_to<String>;
457concept HasResultFromString =
requires(
const String &s) {
458 { T::fromString(s) } -> std::convertible_to<Result<T>>;
468concept HasMemberValueInt =
requires(
const T &t) {
469 { t.value() } -> std::integral;
479concept HasMemberIdInt = (!HasMemberValueInt<T>) &&
requires(
const T &t) {
480 requires std::integral<
decltype(t.id())> || std::is_enum_v<
decltype(t.id())>;
492concept HasMemberToDouble =
requires(
const T &t) {
493 { t.toDouble() } -> std::convertible_to<double>;
504concept HasResultFromDouble =
requires(
double d) {
505 { T::fromDouble(d) } -> std::convertible_to<Result<T>>;
519concept HasMemberToJson =
requires(
const T &t) {
532concept HasResultFromJson =
requires(JsonObject *jp) {
544concept HasIdCtor =
requires {
typename T::ID; } && std::is_constructible_v<T, typename T::ID>;
554concept HasInt64Ctor = std::is_constructible_v<T, int64_t> && !HasIdCtor<T>;
561concept HasPromekiDataType =
requires {
562 { T::promekiDataType::id } -> std::convertible_to<DataTypeID>;
563 { T::promekiDataType::name } -> std::convertible_to<const char *>;
564 { T::promekiDataType::version } -> std::convertible_to<uint32_t>;
587template <
typename T>
struct HasFreeDataStreamWrite : std::false_type {};
590template <
typename T>
struct HasFreeDataStreamRead : std::false_type {};
599template <
typename T, u
int32_t MaxV, u
int32_t CurV = MaxV>
600struct VersionedReader {
601 static Result<T> read(DataStream &s, uint32_t version) {
602 if (version == CurV)
return T::template readFromStream<CurV>(s);
603 if constexpr (CurV > 1)
return VersionedReader<T, MaxV, CurV - 1>::read(s, version);
604 else return makeError<T>(Error::CorruptData);
614template <
typename T,
typename =
void>
615struct ExactDataStreamWrite : std::false_type {};
617template <
typename T,
typename =
void>
618struct ExactDataStreamRead : std::false_type {};
621inline constexpr bool ExactDataStreamWriteV = ExactDataStreamWrite<T>::value;
624inline constexpr bool ExactDataStreamReadV = ExactDataStreamRead<T>::value;
628inline constexpr bool HasDataStreamWriteV = ExactDataStreamWriteV<T> || HasFreeDataStreamWrite<T>::value;
632inline constexpr bool HasDataStreamReadV = ExactDataStreamReadV<T> || HasFreeDataStreamRead<T>::value;
639DataType::Ops makeDefaultOps();
653template <
typename T>
void registerAutoConverters(
const DataType &dt);
676template <
typename T> DataType registerDataType();
691template <
typename T> DataType registerDataType(DataTypeID
id,
const char *name, uint32_t version = 1);
701template <
typename T> DataType DataType::of() {
702 registerBuiltinDataTypes();
703 if constexpr (Detail::HasPromekiDataType<T>) {
704 static const DataType once = registerDataType<T>();
707 return DataType::byCppType(std::type_index(
typeid(T)));
711template <
typename T> DataType registerDataType() {
712 static_assert(Detail::HasPromekiDataType<T>,
713 "registerDataType<T>() with no arguments requires PROMEKI_DATATYPE on T; "
714 "use registerDataType<T>(id, name, version) for primitives and template "
715 "instantiations that cannot host the macro.");
716 DataType existing = DataType::byCppType(std::type_index(
typeid(T)));
717 if (existing.isValid())
return existing;
718 DataType dt = DataType::registerType(
719 T::promekiDataType::id, T::promekiDataType::name, T::promekiDataType::version,
720 std::type_index(
typeid(T)),
sizeof(T),
alignof(T),
721 Detail::makeDefaultOps<T>());
722 if (dt.isValid()) Detail::registerAutoConverters<T>(dt);
726template <
typename T> DataType registerDataType(DataTypeID
id,
const char *name, uint32_t version) {
727 DataType existing = DataType::byCppType(std::type_index(
typeid(T)));
728 if (existing.isValid())
return existing;
729 DataType dt = DataType::registerType(
730 id, name, version, std::type_index(
typeid(T)),
sizeof(T),
alignof(T),
731 Detail::makeDefaultOps<T>());
732 if (dt.isValid()) Detail::registerAutoConverters<T>(dt);
772#define PROMEKI_DATATYPE(TYPE, ID, VERSION) \
773 struct promekiDataType { \
775 static constexpr ::promeki::DataTypeID id = static_cast<::promeki::DataTypeID>(ID); \
776 static constexpr const char *name = #TYPE; \
777 static constexpr uint32_t version = (VERSION); \
778 static ::promeki::Result<Self> dispatchRead(::promeki::DataStream &s, uint32_t v) { \
779 return ::promeki::Detail::VersionedReader<Self, (VERSION)>::read(s, v); \