Loading...
Searching...
No Matches
NodeListMimeSerialization.hpp
1#pragma once
2#include <Device/Node/DeviceNode.hpp>
3
4#include <score/model/tree/TreeNodeSerialization.hpp>
5#include <score/serialization/JSONVisitor.hpp>
6#include <score/serialization/MimeVisitor.hpp>
7
8#include <QDebug>
9
10namespace score::mime
11{
12inline constexpr const char* nodelist() noexcept
13{
14 return "application/x-score-nodelist";
15}
16}
17template <>
18struct MimeReader<Device::NodeList> : public MimeDataReader
19{
20 using MimeDataReader::MimeDataReader;
21 void serialize(const Device::NodeList& lst) const
22 {
23 JSONReader r;
24
25 r.stream.StartArray();
26 for(const auto& elt : lst)
27 {
28 r.stream.StartObject();
29 r.obj["Node"] = *elt;
30 r.obj["Address"] = Device::address(*elt).address;
31 r.stream.EndObject();
32 }
33 r.stream.EndArray();
34
35 m_mime.setData(score::mime::nodelist(), r.toByteArray());
36 }
37};
38
39template <>
40struct MimeWriter<Device::FreeNodeList> : public MimeDataWriter
41{
42 using MimeDataWriter::MimeDataWriter;
43 auto deserialize()
44 {
45 Device::FreeNodeList ml;
46 auto json = readJson(m_mime.data(score::mime::nodelist()));
47
48 // A drag source can declare score::mime::nodelist() with an empty or
49 // malformed payload (an interrupted drag, another app echoing the type
50 // with no data). readJson then yields a document that is not an array,
51 // and rapidjson's GetArray() asserts IsArray() — a SIGABRT that takes
52 // down the whole application. Refuse it: an unusable payload is an
53 // empty node list, not a crash.
54 if(!json.IsArray())
55 {
56 qWarning() << "nodelist drop: payload is not a JSON array ("
57 << m_mime.data(score::mime::nodelist()).size()
58 << "bytes); nothing dropped";
59 return ml;
60 }
61 const auto& arr = json.GetArray();
62
63 auto& strings = score::StringConstant();
64 for(const rapidjson::Value& elt : arr)
65 {
66 // The array's CONTENTS are the same hazard as the array itself, and the
67 // IsArray() guard above does not cover them: rapidjson's operator[]
68 // asserts IsObject() on the value and asserts again when the member is
69 // absent, so a perfectly well-formed `[1,2,3]` or `[{}]` is another
70 // SIGABRT reachable from any external drag source. Skip an entry we
71 // cannot read, and say which one.
72 if(!elt.IsObject())
73 {
74 qWarning() << "nodelist drop: ignoring entry" << int(&elt - arr.Begin())
75 << "- not a JSON object";
76 continue;
77 }
78 if(elt.FindMember(strings.Address.c_str()) == elt.MemberEnd()
79 || elt.FindMember("Node") == elt.MemberEnd())
80 {
81 qWarning() << "nodelist drop: ignoring entry" << int(&elt - arr.Begin())
82 << "- missing its Address or Node member";
83 continue;
84 }
85
87 Device::FreeNode n;
88 n.first <<= des.obj[strings.Address];
89 n.second <<= des.obj["Node"];
90 ml.push_back(n);
91 }
92
93 return ml;
94 }
95};
Definition JSONVisitor.hpp:52
Definition JSONVisitor.hpp:423
Manipulation of Devices from Qt.
Definition AddressSettings.cpp:14
Definition MimeVisitor.hpp:22
Definition MimeVisitor.hpp:32
Definition MimeVisitor.hpp:7
Definition MimeVisitor.hpp:9