File indexing completed on 2024-05-12 05:26:02
0001 /* 0002 * Copyright (C) 2015 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 #include "propertymapper.h" 0021 0022 #include "applicationdomaintype.h" 0023 #include <QDateTime> 0024 #include <QDataStream> 0025 #include <zstd.h> 0026 #include "mail_generated.h" 0027 #include "contact_generated.h" 0028 0029 static QByteArray decompress(const char *data, size_t size) 0030 { 0031 auto decompressedSize = ZSTD_getFrameContentSize(data, size); 0032 if (decompressedSize == ZSTD_CONTENTSIZE_UNKNOWN || decompressedSize == ZSTD_CONTENTSIZE_ERROR) { 0033 qWarning() << "Error during decompression: invalid frame content size." << decompressedSize; 0034 return{}; 0035 } 0036 0037 QByteArray result; 0038 result.resize(decompressedSize); 0039 const auto res = ZSTD_decompress(result.data(), result.size(), data, size); 0040 if (ZSTD_isError(res)) { 0041 qWarning() << "Error during decompression" << ZSTD_getErrorName(res); 0042 return {}; 0043 } 0044 result.resize(res); 0045 return result; 0046 } 0047 0048 static QByteArray compress(const QByteArray &ba) 0049 { 0050 QByteArray result; 0051 result.resize(ZSTD_compressBound(ba.size())); 0052 //The default compression level of the zstd tool 0053 static int compressionLevel = 3; 0054 const auto res = ZSTD_compress(result.data(), result.size(), ba.data(), ba.size(), compressionLevel); 0055 if (ZSTD_isError(res)) { 0056 qWarning() << "Error during compression" << ZSTD_getErrorName(res); 0057 return {}; 0058 } 0059 result.resize(res); 0060 return result; 0061 } 0062 0063 template <> 0064 flatbuffers::uoffset_t variantToProperty<QString>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0065 { 0066 if (property.isValid()) { 0067 const auto str = property.toString(); 0068 if (str.isEmpty()) { 0069 return 0; 0070 } 0071 return fbb.CreateString(str.toStdString()).o; 0072 } 0073 return 0; 0074 } 0075 0076 template <> 0077 flatbuffers::uoffset_t variantToProperty<Sink::ApplicationDomain::Reference>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0078 { 0079 if (property.isValid()) { 0080 return fbb.CreateString(property.value<Sink::ApplicationDomain::Reference>().value.toStdString()).o; 0081 } 0082 return 0; 0083 } 0084 0085 template <> 0086 flatbuffers::uoffset_t variantToProperty<QByteArray>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0087 { 0088 if (property.isValid()) { 0089 const auto ba = property.toByteArray(); 0090 if (ba.isEmpty()) { 0091 return 0; 0092 } 0093 const auto result = compress(ba); 0094 const auto s = fbb.CreateString(result.constData(), result.size()); 0095 return s.o; 0096 } 0097 return 0; 0098 } 0099 0100 template <> 0101 flatbuffers::uoffset_t variantToProperty<QDateTime>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0102 { 0103 if (property.isValid()) { 0104 QByteArray ba; 0105 QDataStream ds(&ba, QIODevice::WriteOnly); 0106 ds << property.toDateTime(); 0107 return fbb.CreateString(ba.toStdString()).o; 0108 } 0109 return 0; 0110 } 0111 0112 template <> 0113 flatbuffers::uoffset_t variantToProperty<QByteArrayList>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0114 { 0115 if (property.isValid()) { 0116 const auto list = property.value<QByteArrayList>(); 0117 std::vector<flatbuffers::Offset<flatbuffers::String>> vector; 0118 for (const auto &value : list) { 0119 auto offset = fbb.CreateString(value.toStdString()); 0120 vector.push_back(offset); 0121 } 0122 return fbb.CreateVector(vector).o; 0123 } 0124 return 0; 0125 } 0126 0127 template <> 0128 flatbuffers::uoffset_t variantToProperty<QStringList>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0129 { 0130 if (property.isValid()) { 0131 const auto list = property.value<QStringList>(); 0132 std::vector<flatbuffers::Offset<flatbuffers::String>> vector; 0133 for (const auto &value : list) { 0134 auto offset = fbb.CreateString(value.toStdString()); 0135 vector.push_back(offset); 0136 } 0137 return fbb.CreateVector(vector).o; 0138 } 0139 return 0; 0140 } 0141 0142 template <> 0143 flatbuffers::uoffset_t variantToProperty<Sink::ApplicationDomain::Mail::Contact>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0144 { 0145 if (property.isValid()) { 0146 const auto value = property.value<Sink::ApplicationDomain::Mail::Contact>(); 0147 return Sink::ApplicationDomain::Buffer::CreateMailContactDirect(fbb, value.name.toUtf8().constData(), value.emailAddress.toUtf8().constData()).o; 0148 } 0149 return 0; 0150 } 0151 0152 template <> 0153 flatbuffers::uoffset_t variantToProperty<QList<Sink::ApplicationDomain::Mail::Contact>>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0154 { 0155 if (property.isValid()) { 0156 const auto list = property.value<QList<Sink::ApplicationDomain::Mail::Contact>>(); 0157 std::vector<flatbuffers::Offset<Sink::ApplicationDomain::Buffer::MailContact>> vector; 0158 for (const auto &value : list) { 0159 auto offset = Sink::ApplicationDomain::Buffer::CreateMailContactDirect(fbb, value.name.toUtf8().constData(), value.emailAddress.toUtf8().constData()).o; 0160 vector.push_back(offset); 0161 } 0162 return fbb.CreateVector(vector).o; 0163 } 0164 return 0; 0165 } 0166 0167 template <> 0168 flatbuffers::uoffset_t variantToProperty<QList<Sink::ApplicationDomain::Contact::Email>>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) 0169 { 0170 if (property.isValid()) { 0171 const auto list = property.value<QList<Sink::ApplicationDomain::Contact::Email>>(); 0172 std::vector<flatbuffers::Offset<Sink::ApplicationDomain::Buffer::ContactEmail>> vector; 0173 for (const auto &value : list) { 0174 auto offset = Sink::ApplicationDomain::Buffer::CreateContactEmailDirect(fbb, value.type, value.email.toUtf8().constData()).o; 0175 vector.push_back(offset); 0176 } 0177 return fbb.CreateVector(vector).o; 0178 } 0179 return 0; 0180 } 0181 0182 0183 QString propertyToString(const flatbuffers::String *property) 0184 { 0185 if (property) { 0186 // We have to copy the memory, otherwise it would become eventually invalid 0187 return QString::fromUtf8(reinterpret_cast<const char *>(property->Data()), property->size()); 0188 } 0189 return QString(); 0190 } 0191 0192 template <> 0193 QVariant propertyToVariant<QString>(const flatbuffers::String *property) 0194 { 0195 if (property) { 0196 // We have to copy the memory, otherwise it would become eventually invalid 0197 return propertyToString(property); 0198 } 0199 return QVariant(); 0200 } 0201 0202 template <> 0203 QVariant propertyToVariant<Sink::ApplicationDomain::Reference>(const flatbuffers::String *property) 0204 { 0205 if (property) { 0206 // We have to copy the memory, otherwise it would become eventually invalid 0207 return QVariant::fromValue(Sink::ApplicationDomain::Reference{QByteArray(reinterpret_cast<const char *>(property->Data()), property->size())}); 0208 } 0209 return QVariant(); 0210 } 0211 0212 template <> 0213 QVariant propertyToVariant<QByteArray>(const flatbuffers::String *property) 0214 { 0215 if (property) { 0216 return decompress(property->c_str(), property->size()); 0217 } 0218 return QVariant(); 0219 } 0220 0221 template <> 0222 QVariant propertyToVariant<QByteArray>(const flatbuffers::Vector<uint8_t> *property) 0223 { 0224 if (property) { 0225 // We have to copy the memory, otherwise it would become eventually invalid 0226 return QByteArray(reinterpret_cast<const char *>(property->Data()), property->size()); 0227 } 0228 return QVariant(); 0229 } 0230 0231 template <> 0232 QVariant propertyToVariant<QByteArrayList>(const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *property) 0233 { 0234 if (property) { 0235 QByteArrayList list; 0236 for (auto it = property->begin(); it != property->end();) { 0237 // We have to copy the memory, otherwise it would become eventually invalid 0238 list << QString::fromStdString((*it)->str()).toUtf8(); 0239 it.operator++(); 0240 } 0241 return QVariant::fromValue(list); 0242 } 0243 return QVariant(); 0244 } 0245 0246 template <> 0247 QVariant propertyToVariant<QStringList>(const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *property) 0248 { 0249 if (property) { 0250 QStringList list; 0251 for (auto it = property->begin(); it != property->end();) { 0252 // We have to copy the memory, otherwise it would become eventually invalid 0253 list << QString::fromStdString((*it)->str()); 0254 it.operator++(); 0255 } 0256 return QVariant::fromValue(list); 0257 } 0258 return QVariant(); 0259 } 0260 0261 template <> 0262 QVariant propertyToVariant<Sink::ApplicationDomain::Mail::Contact>(const Sink::ApplicationDomain::Buffer::MailContact *property) 0263 { 0264 if (property) { 0265 return QVariant::fromValue(Sink::ApplicationDomain::Mail::Contact{propertyToString(property->name()), propertyToString(property->email())}); 0266 } 0267 return QVariant(); 0268 0269 } 0270 0271 template <> 0272 QVariant propertyToVariant<QList<Sink::ApplicationDomain::Mail::Contact>>(const flatbuffers::Vector<flatbuffers::Offset<Sink::ApplicationDomain::Buffer::MailContact>> *property) 0273 { 0274 if (property) { 0275 QList<Sink::ApplicationDomain::Mail::Contact> list; 0276 for (auto it = property->begin(); it != property->end();) { 0277 // We have to copy the memory, otherwise it would become eventually invalid 0278 list << Sink::ApplicationDomain::Mail::Contact{propertyToString(it->name()), propertyToString(it->email())}; 0279 it.operator++(); 0280 } 0281 return QVariant::fromValue(list); 0282 } 0283 return QVariant(); 0284 } 0285 0286 template <> 0287 QVariant propertyToVariant<QList<Sink::ApplicationDomain::Contact::Email>>(const flatbuffers::Vector<flatbuffers::Offset<Sink::ApplicationDomain::Buffer::ContactEmail>> *property) 0288 { 0289 if (property) { 0290 QList<Sink::ApplicationDomain::Contact::Email> list; 0291 for (auto it = property->begin(); it != property->end();) { 0292 list << Sink::ApplicationDomain::Contact::Email{static_cast<Sink::ApplicationDomain::Contact::Email::Type>(it->type()), propertyToString(it->email())}; 0293 it.operator++(); 0294 } 0295 return QVariant::fromValue(list); 0296 } 0297 return QVariant(); 0298 } 0299 0300 template <> 0301 QVariant propertyToVariant<bool>(uint8_t property) 0302 { 0303 return bool(property); 0304 } 0305 0306 template <> 0307 QVariant propertyToVariant<int>(uint8_t property) 0308 { 0309 return static_cast<int>(property); 0310 } 0311 0312 template <> 0313 QVariant propertyToVariant<int>(int property) 0314 { 0315 return property; 0316 } 0317 0318 template <> 0319 QVariant propertyToVariant<bool>(int property) 0320 { 0321 return bool(property); 0322 } 0323 0324 template <> 0325 QVariant propertyToVariant<QDateTime>(const flatbuffers::String *property) 0326 { 0327 if (property) { 0328 auto ba = QByteArray::fromRawData(property->c_str(), property->size()); 0329 QDateTime dt; 0330 QDataStream ds(&ba, QIODevice::ReadOnly); 0331 ds >> dt; 0332 return dt; 0333 } 0334 return QVariant(); 0335 }