#ifndef QTJSONSERIALIZER_TYPECONVERTER_H #define QTJSONSERIALIZER_TYPECONVERTER_H #include "qtjsonserializer_global.h" #include #include #include #include #include #include #include #include namespace QtJsonSerializer { //! Interface to extract data from any generic container class Q_JSONSERIALIZER_EXPORT TypeExtractor { Q_DISABLE_COPY(TypeExtractor) public: TypeExtractor(); virtual ~TypeExtractor(); //! Returns the identifier of the general type this extractor is for virtual QByteArray baseType() const = 0; //! Returns an ordered list of subtypes found in types handled by this extractor virtual QList subtypes() const = 0; //! Extracts the data of a value of the extractors type at the given index virtual QVariant extract(const QVariant &value, int index = -1) const = 0; //! Emplaces the value into the target of the extractors type at the given index virtual void emplace(QVariant &target, const QVariant &value, int index = -1) const = 0; }; class TypeConverterPrivate; //! An interface to create custom serializer type converters class Q_JSONSERIALIZER_EXPORT TypeConverter { Q_DISABLE_COPY(TypeConverter) public: //! A placeholder tag to be used if no tag is expected/allowed/given static constexpr auto NoTag = static_cast(std::numeric_limits>::max()); //! Sample values for a priority value (default converters are mostly Standard and are guaranteed to be between Low and High) enum Priority : int { ExtremlyLow = -0x00FFFFFF, VeryLow = -0x0000FFFF, Low = -0x000000FF, Standard = 0x00000000, High = 0x000000FF, VeryHigh = 0x0000FFFF, ExtremlyHigh = 0x00FFFFFF }; //! The possible results of canDeserialize(), used internally only enum DeserializationCapabilityResult : int { Positive = 1, //!< The converter can deserialize the given data Guessed = 2, //!< The converter guessed a type for the given data Negative = -1, //!< The converter cannot deserialize the given data WrongTag = -2 //!< The converter could deserialize the given data, but the tag does not match }; //! Helper class passed to the type converter by the serializer. Do not implement yourself class Q_JSONSERIALIZER_EXPORT SerializationHelper { Q_DISABLE_COPY(SerializationHelper) public: SerializationHelper(); virtual ~SerializationHelper(); //! Returns true, if de/serializing to JSON, and false for CBOR virtual bool jsonMode() const = 0; //! Returns a property from the serializer virtual QVariant getProperty(const char *name) const = 0; //! Returns a tag registered for the given metaTypeId virtual QCborTag typeTag(int metaTypeId) const = 0; //! Returns a reference to an extractor for the given type, or nullptr virtual QSharedPointer extractor(int metaTypeId) const = 0; //! Serialize a subvalue, represented by a meta property virtual QCborValue serializeSubtype(const QMetaProperty &property, const QVariant &value) const = 0; //! Serialize a subvalue, represented by a type id virtual QCborValue serializeSubtype(int propertyType, const QVariant &value, const QByteArray &traceHint = {}) const = 0; //! Deserialize a subvalue, represented by a meta property virtual QVariant deserializeSubtype(const QMetaProperty &property, const QCborValue &value, QObject *parent) const = 0; //! Deserialize a subvalue, represented by a type id virtual QVariant deserializeSubtype(int propertyType, const QCborValue &value, QObject *parent, const QByteArray &traceHint = {}) const = 0; }; //! Constructor TypeConverter(); //! Destructor virtual ~TypeConverter(); //! The name of the converter. Used for debugging purpose virtual QByteArray name() const = 0; //! Returns the priority of this converter int priority() const; //! Sets the priority of this converter void setPriority(int priority); //! Returns the helper associated with this converter const SerializationHelper *helper() const; //! @private void setHelper(const SerializationHelper *helper); //! Returns true, if this implementation can convert the given type virtual bool canConvert(int metaTypeId) const = 0; //! Returns a list of allowed tags for the given type virtual QList allowedCborTags(int metaTypeId) const; //! Returns a list of allowed types for the given type and tag virtual QList allowedCborTypes(int metaTypeId, QCborTag tag) const = 0; //! Returns a type guessed from the tag and data, that is supported by the converter virtual int guessType(QCborTag tag, QCborValue::Type dataType) const; //! @private DeserializationCapabilityResult canDeserialize(int &metaTypeId, QCborTag tag, QCborValue::Type dataType) const; //! Called by the serializer to serializer your given type to CBOR virtual QCborValue serialize(int propertyType, const QVariant &value) const = 0; //! Called by the serializer to deserializer your given type from CBOR virtual QVariant deserializeCbor(int propertyType, const QCborValue &value, QObject *parent) const = 0; //! Called by the serializer to deserializer your given type from JSON virtual QVariant deserializeJson(int propertyType, const QCborValue &value, QObject *parent) const; private: QScopedPointer d; void mapTypesToJson(QList &typeList) const; }; //! Macro to implement the TypeConverter::name method in a subclass #define QT_JSONSERIALIZER_TYPECONVERTER_NAME(className) inline QByteArray name() const override { \ static_assert(std::is_same_v>); \ return QByteArrayLiteral(#className); \ } //! A factory interface to create instances of QJsonTypeConverters class Q_JSONSERIALIZER_EXPORT TypeConverterFactory { Q_DISABLE_COPY(TypeConverterFactory) public: TypeConverterFactory(); virtual ~TypeConverterFactory(); //! The primary factory method to create converters virtual QSharedPointer createConverter() const = 0; }; //! A template implementation of TypeConverterFactory to generically create simply converters template class TypeConverterStandardFactory : public TypeConverterFactory { public: QSharedPointer createConverter() const override; }; // ------------- GENERIC IMPLEMENTATION ------------- template QSharedPointer TypeConverterStandardFactory::createConverter() const { auto converter = QSharedPointer::create(); if (OverwritePriority != TypeConverter::Priority::Standard) converter->setPriority(OverwritePriority); return converter; } } #endif // QTJSONSERIALIZER_TYPECONVERTER_H