12#include "open62541pp/config.hpp"
44#ifdef UA_ENABLE_TYPEDESCRIPTION
51 void setTypeName([[maybe_unused]]
const char* typeName)
noexcept {
52#ifdef UA_ENABLE_TYPEDESCRIPTION
53 handle()->typeName = typeName;
66#if UAPP_OPEN62541_VER_GE(1, 2)
74#if UAPP_OPEN62541_VER_GE(1, 2)
121 return lhs.typeId == rhs.typeId;
125 return !(lhs == rhs);
129#if UAPP_OPEN62541_VER_GE(1, 3)
130 if (lhs.memberType ==
nullptr || rhs.memberType ==
nullptr) {
133 return (lhs.memberType == rhs.memberType) || (*lhs.memberType == *rhs.memberType);
135 return lhs.memberTypeIndex == rhs.memberTypeIndex;
140 return !(lhs == rhs);
148 const char* memberName,
156 const char* typeName,
163 uint32_t membersSize,
177template <auto memberPtr>
184template <
typename T,
typename TMember>
187 return size_t(&(
object.*member)) - size_t(&
object);
190struct TagDataTypeAny;
191struct TagDataTypeEnum;
192struct TagDataTypeStruct;
193struct TagDataTypeUnion;
203template <
typename T,
typename Tag = detail::TagDataTypeAny,
typename U = struct DeferT>
212 static auto createEnum(
const char* typeName,
NodeId typeId,
NodeId binaryEncodingId);
221 static auto createStructure(
const char* typeName,
NodeId typeId,
NodeId binaryEncodingId);
230 static auto createUnion(
const char* typeName,
NodeId typeId,
NodeId binaryEncodingId);
238 template <auto U::*field>
239 auto& addField(
const char* fieldName,
const UA_DataType& fieldType);
245 template <auto U::*field>
247 return addField<field>(fieldName, detail::getMemberDataType<field>());
259 template <auto U::*fieldSize, auto U::*fieldArray>
260 auto& addField(
const char* fieldName,
const UA_DataType& fieldType);
266 template <auto U::*fieldSize, auto U::*fieldArray>
268 return addField<fieldSize, fieldArray>(fieldName, detail::getMemberDataType<fieldArray>());
278 template <auto U::*memberUnion,
typename TField>
279 auto& addUnionField(
const char* fieldName,
const UA_DataType& fieldType);
285 template <auto U::*memberUnion,
typename TField>
287 return addUnionField<memberUnion, TField>(fieldName, getDataType<TField>());
296 template <
typename,
typename,
typename>
300 : dataType_(std::move(dataType)) {}
309 std::vector<Field> fields_;
314template <
typename T,
typename Tag,
typename U>
316 const char* typeName,
NodeId typeId,
NodeId binaryEncodingId
318 static_assert(std::is_enum_v<T>,
"T must be an enum");
330template <
typename T,
typename Tag,
typename U>
332 const char* typeName,
NodeId typeId,
NodeId binaryEncodingId
334 static_assert(std::is_class_v<T>,
"T must be a struct or class");
346template <
typename T,
typename Tag,
typename U>
348 const char* typeName,
NodeId typeId,
NodeId binaryEncodingId
350 static_assert(std::is_class_v<T>,
"T must be a struct or class");
362template <
typename T,
typename Tag,
typename U>
363template <auto U::*field>
367 std::is_same_v<Tag, detail::TagDataTypeStruct>,
368 "Built type must be a struct or class to add members"
370 assert(
sizeof(std::remove_pointer_t<TMember>) == fieldType.
memSize);
371 if (std::is_pointer_v<TMember>) {
374 if (std::is_pointer_v<TMember> || !fieldType.
pointerFree) {
375 dataType_.setPointerFree(
false);
385 std::is_pointer_v<TMember>
391template <
typename T,
typename Tag,
typename U>
392template <auto U::*fieldSize, auto U::*fieldArray>
397 std::is_same_v<Tag, detail::TagDataTypeStruct>,
398 "Built type must be a struct or class to add members"
400 static_assert(std::is_integral_v<TSize>,
"TSize must be an integral type");
401 static_assert(std::is_pointer_v<TArray>,
"TArray must be a pointer");
404 "No padding between members size and array allowed"
406 assert(
sizeof(std::remove_pointer_t<TArray>) == fieldType.
memSize);
407 dataType_.setPointerFree(
false);
409 sizeof(TSize) +
sizeof(TArray),
422template <
typename T,
typename Tag,
typename U>
423template <auto U::*memberUnion,
typename TField>
425 const char* fieldName,
const UA_DataType& fieldType
429 std::is_same_v<Tag, detail::TagDataTypeUnion>,
430 "Built type must be a union to add union fields"
432 static_assert(std::is_union_v<TUnion>,
"TUnion must be a union");
433 static_assert(
sizeof(TField) <=
sizeof(TUnion),
"TField exceeds size of union");
435 assert(offset > 0 &&
"A union type must consist of a switch field and a union");
436 assert(
sizeof(std::remove_pointer_t<TField>) == fieldType.
memSize);
437 if (std::is_pointer_v<TField> || !fieldType.
pointerFree) {
438 dataType_.setPointerFree(
false);
446 static_cast<uint8_t
>(offset),
448 std::is_pointer_v<TField>
454template <
typename T,
typename Tag,
typename U>
456 static_assert(!std::is_same_v<Tag, detail::TagDataTypeAny>);
458 std::sort(fields_.begin(), fields_.end(), [](
const auto& lhs,
const auto& rhs) {
459 return lhs.offset < rhs.offset;
462 if constexpr (std::is_same_v<Tag, detail::TagDataTypeStruct>) {
463 for (
auto it = fields_.begin(); it < fields_.end(); ++it) {
464 if (it == fields_.begin()) {
465 it->dataTypeMember.padding =
static_cast<uint8_t
>(it->offset);
467 it->dataTypeMember.padding =
static_cast<uint8_t
>(
468 it->offset - (std::prev(it)->offset + std::prev(it)->memSize)
474 std::vector<DataTypeMember> dataTypeMembers(fields_.size());
475 std::transform(fields_.cbegin(), fields_.cend(), dataTypeMembers.begin(), [](
auto&& m) {
476 return m.dataTypeMember;
478 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.
uint16_t getMemSize() const noexcept
void setTypeKind(uint8_t typeKind) noexcept
DataType & operator=(DataType &&other) noexcept
DataType(const UA_DataType &native)
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
Span< const DataTypeMember > getMembers() const noexcept
DataType & operator=(const DataType &other)
DataType(UA_DataType &&native)
DataType(const DataType &other)
auto getIdentifierAs() const
Get identifier by template type.
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
UA_DataTypeMember createDataTypeMember(const char *memberName, const UA_DataType &memberType, uint8_t padding, bool isArray, bool isOptional) noexcept
UA_DataTypeArray createDataTypeArray(Span< const DataType > types, const UA_DataTypeArray *next=nullptr) noexcept
UA_DataType createDataType(const char *typeName, UA_NodeId typeId, UA_NodeId binaryEncodingId, uint16_t memSize, uint8_t typeKind, bool pointerFree, bool overlayable, uint32_t membersSize, DataTypeMember *members) noexcept
const UA_DataType & getMemberDataType()
size_t offsetOfMember(TMember T::*member)
typename MemberType< T >::type MemberTypeT
uint16_t TypeIndex
Type index of the UA_TYPES array.
Client * asWrapper(UA_Client *client) noexcept
Convert native UA_Client pointer to its wrapper instance.
bool operator!=(const Client &lhs, const Client &rhs) noexcept
@ NodeId
Unambiguous identifier of a node.
const UA_DataType & getDataType() noexcept
bool operator==(const Client &lhs, const Client &rhs) noexcept
UA_DataTypeMember * members
UA_NodeId binaryEncodingId
UA_DATATYPEKIND_OPTSTRUCT
UA_DATATYPEKIND_STRUCTURE