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 }