File indexing completed on 2024-05-12 05:26:02
0001 /* 0002 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm> 0003 * 0004 * This program is free software; you can redistribute it and/or modify 0005 * it under the terms of the GNU General Public License as published by 0006 * the Free Software Foundation; either version 2 of the License, or 0007 * (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the 0016 * Free Software Foundation, Inc., 0017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 0018 */ 0019 0020 #pragma once 0021 0022 #include "sink_export.h" 0023 #include <QVariant> 0024 #include <QByteArray> 0025 #include <functional> 0026 #include <flatbuffers/flatbuffers.h> 0027 0028 namespace Sink { 0029 namespace ApplicationDomain { 0030 namespace Buffer { 0031 struct MailContact; 0032 struct ContactEmail; 0033 } 0034 } 0035 } 0036 0037 /** 0038 * Defines how to convert qt primitives to flatbuffer ones 0039 */ 0040 template <class T> 0041 flatbuffers::uoffset_t SINK_EXPORT variantToProperty(const QVariant &, flatbuffers::FlatBufferBuilder &fbb); 0042 0043 /** 0044 * Defines how to convert flatbuffer primitives to qt ones 0045 */ 0046 template <typename T> 0047 QVariant SINK_EXPORT propertyToVariant(const flatbuffers::String *); 0048 template <typename T> 0049 QVariant SINK_EXPORT propertyToVariant(uint8_t); 0050 template <typename T> 0051 QVariant SINK_EXPORT propertyToVariant(int); 0052 template <typename T> 0053 QVariant SINK_EXPORT propertyToVariant(const flatbuffers::Vector<uint8_t> *); 0054 template <typename T> 0055 QVariant SINK_EXPORT propertyToVariant(const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *); 0056 template <typename T> 0057 QVariant SINK_EXPORT propertyToVariant(const Sink::ApplicationDomain::Buffer::MailContact *); 0058 template <typename T> 0059 QVariant SINK_EXPORT propertyToVariant(const flatbuffers::Vector<flatbuffers::Offset<Sink::ApplicationDomain::Buffer::MailContact>> *); 0060 template <typename T> 0061 QVariant SINK_EXPORT propertyToVariant(const flatbuffers::Vector<flatbuffers::Offset<Sink::ApplicationDomain::Buffer::ContactEmail>> *); 0062 0063 /** 0064 * The property mapper is a non-typesafe virtual dispatch. 0065 * 0066 * Instead of using an interface and requring each implementation to override 0067 * a virtual method per property, the property mapper can be filled with accessors 0068 * that extract the properties from resource types. 0069 */ 0070 class PropertyMapper 0071 { 0072 public: 0073 virtual ~PropertyMapper(){}; 0074 0075 template <typename T, typename Buffer, typename BufferBuilder, typename FunctionReturnValue, typename Arg> 0076 void addMapping(FunctionReturnValue (Buffer::*f)() const, void (BufferBuilder::*f2)(Arg)) 0077 { 0078 addReadMapping<T, Buffer, FunctionReturnValue>(f); 0079 addWriteMapping<T, BufferBuilder>(f2); 0080 } 0081 0082 virtual QVariant getProperty(const QByteArray &key, void const *buffer) const 0083 { 0084 const auto it = mReadAccessors.constFind(key); 0085 if (it != mReadAccessors.end()) { 0086 const auto accessor = it.value(); 0087 return accessor(buffer); 0088 } 0089 Q_ASSERT_X(false, key, "No read accessor for the property"); 0090 return {}; 0091 } 0092 0093 virtual void setProperty(const QByteArray &key, const QVariant &value, QList<std::function<void(void *builder)>> &builderCalls, flatbuffers::FlatBufferBuilder &fbb) const 0094 { 0095 const auto it = mWriteAccessors.constFind(key); 0096 if (it != mWriteAccessors.end()) { 0097 const auto accessor = it.value(); 0098 builderCalls << accessor(value, fbb); 0099 } else { 0100 Q_ASSERT_X(false, key, "No write accessor for the property"); 0101 } 0102 } 0103 0104 bool hasMapping(const QByteArray &key) const 0105 { 0106 return mReadAccessors.contains(key); 0107 } 0108 0109 QList<QByteArray> availableProperties() const 0110 { 0111 return mReadAccessors.keys(); 0112 } 0113 0114 private: 0115 void addReadMapping(const QByteArray &property, const std::function<QVariant(void const *)> &mapping) 0116 { 0117 mReadAccessors.insert(property, mapping); 0118 } 0119 0120 template <typename T, typename Buffer, typename FunctionReturnValue> 0121 void addReadMapping(FunctionReturnValue (Buffer::*f)() const) 0122 { 0123 addReadMapping(T::name, [f](void const *buffer) -> QVariant { return propertyToVariant<typename T::Type>((static_cast<const Buffer*>(buffer)->*f)()); }); 0124 } 0125 0126 0127 void addWriteMapping(const QByteArray &property, const std::function<std::function<void(void *builder)>(const QVariant &, flatbuffers::FlatBufferBuilder &)> &mapping) 0128 { 0129 mWriteAccessors.insert(property, mapping); 0130 } 0131 0132 template <typename T, typename BufferBuilder> 0133 void addWriteMapping(void (BufferBuilder::*f)(uint8_t)) 0134 { 0135 addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { 0136 return [value, f](void *builder) { (static_cast<BufferBuilder*>(builder)->*f)(value.value<typename T::Type>()); }; 0137 }); 0138 } 0139 0140 template <typename T, typename BufferBuilder> 0141 void addWriteMapping(void (BufferBuilder::*f)(int)) 0142 { 0143 addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { 0144 return [value, f](void *builder) { (static_cast<BufferBuilder*>(builder)->*f)(value.value<typename T::Type>()); }; 0145 }); 0146 } 0147 0148 template <typename T, typename BufferBuilder> 0149 void addWriteMapping(void (BufferBuilder::*f)(bool)) 0150 { 0151 addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { 0152 return [value, f](void *builder) { (static_cast<BufferBuilder*>(builder)->*f)(value.value<typename T::Type>()); }; 0153 }); 0154 } 0155 0156 template <typename T, typename BufferBuilder, typename Arg> 0157 void addWriteMapping(void (BufferBuilder::*f)(flatbuffers::Offset<Arg>)) 0158 { 0159 addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { 0160 auto offset = variantToProperty<typename T::Type>(value, fbb); 0161 return [offset, f](void *builder) { (static_cast<BufferBuilder*>(builder)->*f)(offset); }; 0162 }); 0163 } 0164 0165 QHash<QByteArray, std::function<QVariant(void const *)>> mReadAccessors; 0166 QHash<QByteArray, std::function<std::function<void(void *builder)>(const QVariant &, flatbuffers::FlatBufferBuilder &)>> mWriteAccessors; 0167 }; 0168