12#include "open62541pp/config.hpp"
45#ifdef UA_ENABLE_TYPEDESCRIPTION
53 [[deprecated(
"use typeName() instead")]]
59#ifdef UA_ENABLE_TYPEDESCRIPTION
69 [[deprecated(
"use typeId() instead")]]
79#if UAPP_OPEN62541_VER_GE(1, 2)
87 [[deprecated(
"use binaryEncodingId() instead")]]
93#if UAPP_OPEN62541_VER_GE(1, 2)
105 [[deprecated(
"use memSize() instead")]]
119 [[deprecated(
"use typeKind() instead")]]
133 [[deprecated(
"use pointerFree() instead")]]
147 [[deprecated(
"use overlayable() instead")]]
161 [[deprecated(
"use members() instead")]]
171 return lhs.typeId == rhs.typeId;
176 return !(lhs == rhs);
181#if UAPP_OPEN62541_VER_GE(1, 3)
182 if (lhs.memberType ==
nullptr || rhs.memberType ==
nullptr) {
185 return (lhs.memberType == rhs.memberType) || (*lhs.memberType == *rhs.memberType);
187 return lhs.memberTypeIndex == rhs.memberTypeIndex;
193 return !(lhs == rhs);
201 const char* memberName,
209 const char* typeName,
216 uint32_t membersSize,
230template <auto memberPtr>
232 using TMember = detail::MemberTypeT<
decltype(memberPtr)>;
237template <
typename T,
typename TMember>
238size_t offsetOfMember(TMember T::*member) {
240 return size_t(&(
object.*member)) - size_t(&
object);
243struct TagDataTypeAny;
244struct TagDataTypeEnum;
245struct TagDataTypeStruct;
246struct TagDataTypeUnion;
256template <
typename T,
typename Tag = detail::TagDataTypeAny,
typename U = struct DeferT>
265 static auto createEnum(
const char* typeName,
NodeId typeId,
NodeId binaryEncodingId);
274 static auto createStructure(
const char* typeName,
NodeId typeId,
NodeId binaryEncodingId);
283 static auto createUnion(
const char* typeName,
NodeId typeId,
NodeId binaryEncodingId);
291 template <auto U::*field>
292 auto& addField(
const char* fieldName,
const UA_DataType& fieldType);
298 template <auto U::*field>
300 return addField<field>(fieldName, detail::getMemberDataType<field>());
312 template <auto U::*fieldSize, auto U::*fieldArray>
313 auto& addField(
const char* fieldName,
const UA_DataType& fieldType);
319 template <auto U::*fieldSize, auto U::*fieldArray>
321 return addField<fieldSize, fieldArray>(fieldName, detail::getMemberDataType<fieldArray>());
331 template <auto U::*memberUnion,
typename TField>
332 auto& addUnionField(
const char* fieldName,
const UA_DataType& fieldType);
338 template <auto U::*memberUnion,
typename TField>
340 return addUnionField<memberUnion, TField>(fieldName, getDataType<TField>());
349 template <
typename,
typename,
typename>
353 : dataType_(std::move(dataType)) {}
362 std::vector<Field> fields_;
367template <
typename T,
typename Tag,
typename U>
369 const char* typeName,
NodeId typeId,
NodeId binaryEncodingId
371 static_assert(std::is_enum_v<T>,
"T must be an enum");
383template <
typename T,
typename Tag,
typename U>
385 const char* typeName,
NodeId typeId,
NodeId binaryEncodingId
387 static_assert(std::is_class_v<T>,
"T must be a struct or class");
399template <
typename T,
typename Tag,
typename U>
401 const char* typeName,
NodeId typeId,
NodeId binaryEncodingId
403 static_assert(std::is_class_v<T>,
"T must be a struct or class");
415template <
typename T,
typename Tag,
typename U>
416template <auto U::*field>
418 using TMember = detail::MemberTypeT<
decltype(field)>;
420 std::is_same_v<Tag, detail::TagDataTypeStruct>,
421 "Built type must be a struct or class to add members"
423 assert(
sizeof(std::remove_pointer_t<TMember>) == fieldType.
memSize);
424 if (std::is_pointer_v<TMember>) {
427 if (std::is_pointer_v<TMember> || !fieldType.
pointerFree) {
428 dataType_.setPointerFree(
false);
432 detail::offsetOfMember(field),
433 detail::createDataTypeMember(
438 std::is_pointer_v<TMember>
444template <
typename T,
typename Tag,
typename U>
445template <auto U::*fieldSize, auto U::*fieldArray>
447 using TSize = detail::MemberTypeT<
decltype(fieldSize)>;
448 using TArray = detail::MemberTypeT<
decltype(fieldArray)>;
450 std::is_same_v<Tag, detail::TagDataTypeStruct>,
451 "Built type must be a struct or class to add members"
453 static_assert(std::is_integral_v<TSize>,
"TSize must be an integral type");
454 static_assert(std::is_pointer_v<TArray>,
"TArray must be a pointer");
456 detail::offsetOfMember(fieldArray) == detail::offsetOfMember(fieldSize) +
sizeof(TSize) &&
457 "No padding between members size and array allowed"
459 assert(
sizeof(std::remove_pointer_t<TArray>) == fieldType.
memSize);
460 dataType_.setPointerFree(
false);
462 sizeof(TSize) +
sizeof(TArray),
463 detail::offsetOfMember(fieldSize),
464 detail::createDataTypeMember(
475template <
typename T,
typename Tag,
typename U>
476template <auto U::*memberUnion,
typename TField>
478 const char* fieldName,
const UA_DataType& fieldType
480 using TUnion = detail::MemberTypeT<
decltype(memberUnion)>;
482 std::is_same_v<Tag, detail::TagDataTypeUnion>,
483 "Built type must be a union to add union fields"
485 static_assert(std::is_union_v<TUnion>,
"TUnion must be a union");
486 static_assert(
sizeof(TField) <=
sizeof(TUnion),
"TField exceeds size of union");
487 const auto offset = detail::offsetOfMember(memberUnion);
488 assert(offset > 0 &&
"A union type must consist of a switch field and a union");
489 assert(
sizeof(std::remove_pointer_t<TField>) == fieldType.
memSize);
490 if (std::is_pointer_v<TField> || !fieldType.
pointerFree) {
491 dataType_.setPointerFree(
false);
496 detail::createDataTypeMember(
499 static_cast<uint8_t
>(offset),
501 std::is_pointer_v<TField>
507template <
typename T,
typename Tag,
typename U>
509 static_assert(!std::is_same_v<Tag, detail::TagDataTypeAny>);
511 std::sort(fields_.begin(), fields_.end(), [](
const auto& lhs,
const auto& rhs) {
512 return lhs.offset < rhs.offset;
515 if constexpr (std::is_same_v<Tag, detail::TagDataTypeStruct>) {
516 for (
auto it = fields_.begin(); it < fields_.end(); ++it) {
517 if (it == fields_.begin()) {
518 it->dataTypeMember.padding =
static_cast<uint8_t
>(it->offset);
520 it->dataTypeMember.padding =
static_cast<uint8_t
>(
521 it->offset - (std::prev(it)->offset + std::prev(it)->memSize)
527 std::vector<DataTypeMember> dataTypeMembers(fields_.size());
528 std::transform(fields_.cbegin(), fields_.cend(), dataTypeMembers.begin(), [](
auto&& m) {
529 return m.dataTypeMember;
531 dataType_.setMembers(dataTypeMembers);
Builder to create DataType definitions of custom types.
DataType build()
Create the actual DataType.
auto & addField(const char *fieldName)
Add a structure array field (derive DataType from fieldArray).
static auto createEnum(const char *typeName, NodeId typeId, NodeId binaryEncodingId)
Build a DataType definition for an enum.
static auto createStructure(const char *typeName, NodeId typeId, NodeId binaryEncodingId)
Build a DataType definition for a structure.
auto & addField(const char *fieldName)
Add a structure field (derive DataType from field).
static auto createUnion(const char *typeName, NodeId typeId, NodeId binaryEncodingId)
Build a DataType definition for an union.
auto & addUnionField(const char *fieldName, const UA_DataType &fieldType)
Add a union field.
auto & addField(const char *fieldName, const UA_DataType &fieldType)
Add a structure field.
auto & addUnionField(const char *fieldName)
Add a union field (derive DataType from TField).
UA_DataType wrapper class.
bool operator!=(const UA_DataTypeMember &lhs, const UA_DataTypeMember &rhs) noexcept
bool operator!=(const UA_DataType &lhs, const UA_DataType &rhs) noexcept
Span< const DataTypeMember > members() const noexcept
bool pointerFree() const noexcept
NodeId binaryEncodingId() const noexcept
uint8_t typeKind() const noexcept
bool overlayable() const noexcept
uint16_t getMemSize() const noexcept
void setTypeKind(uint8_t typeKind) noexcept
uint16_t memSize() const noexcept
DataType & operator=(DataType &&other) noexcept
DataType(const UA_DataType &native)
const char * typeName() const noexcept
NodeId typeId() const noexcept
bool getPointerFree() const noexcept
void setTypeId(NodeId typeId)
NodeId getBinaryEncodingId() const noexcept
DataType(DataType &&other) noexcept
DataType(TypeIndex typeIndex)
void setOverlayable(bool overlayable) noexcept
bool getOverlayable() const noexcept
uint8_t getTypeKind() const noexcept
void setMembers(Span< const DataTypeMember > members)
void setMemSize(uint16_t memSize) noexcept
const char * getTypeName() const noexcept
void setPointerFree(bool pointerFree) noexcept
constexpr DataType()=default
void setBinaryEncodingId(NodeId binaryEncodingId)
void setTypeName(const char *typeName) noexcept
NodeId getTypeId() const noexcept
bool operator==(const UA_DataType &lhs, const UA_DataType &rhs) noexcept
bool operator==(const UA_DataTypeMember &lhs, const UA_DataTypeMember &rhs) noexcept
Span< const DataTypeMember > getMembers() const noexcept
DataType & operator=(const DataType &other)
DataType(UA_DataType &&native)
DataType(const DataType &other)
NamespaceIndex namespaceIndex() const noexcept
T & identifier()
Get identifier reference.
View to a contiguous sequence of objects, similar to std::span in C++20.
Template base class to wrap native objects.
constexpr const UA_DataType & native() const noexcept
constexpr UA_DataType * handle() noexcept
constexpr WrapperType * asWrapper(NativeType *native) noexcept
uint16_t TypeIndex
Type index of the UA_TYPES array.
@ NodeId
Unambiguous identifier of a node.
const UA_DataType & getDataType() noexcept
UA_DataTypeMember * members
UA_NodeId binaryEncodingId
UA_DATATYPEKIND_OPTSTRUCT
UA_DATATYPEKIND_STRUCTURE