1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef dap_serialization_h
16#define dap_serialization_h
17
18#include "typeof.h"
19#include "types.h"
20
21#include <cstddef> // ptrdiff_t
22#include <type_traits>
23
24namespace dap {
25
26// Field describes a single field of a struct.
27struct Field {
28 std::string name; // name of the field
29 ptrdiff_t offset; // offset of the field to the base of the struct
30 const TypeInfo* type; // type of the field
31};
32
33////////////////////////////////////////////////////////////////////////////////
34// Deserializer
35////////////////////////////////////////////////////////////////////////////////
36
37// Deserializer is the interface used to decode data from structured storage.
38// Methods that return a bool use this to indicate success.
39class Deserializer {
40 public:
41 virtual ~Deserializer() = default;
42
43 // deserialization methods for simple data types.
44 // If the stored object is not of the correct type, then these function will
45 // return false.
46 virtual bool deserialize(boolean*) const = 0;
47 virtual bool deserialize(integer*) const = 0;
48 virtual bool deserialize(number*) const = 0;
49 virtual bool deserialize(string*) const = 0;
50 virtual bool deserialize(object*) const = 0;
51 virtual bool deserialize(any*) const = 0;
52
53 // count() returns the number of elements in the array object referenced by
54 // this Deserializer.
55 virtual size_t count() const = 0;
56
57 // array() calls the provided std::function for deserializing each array
58 // element in the array object referenced by this Deserializer.
59 virtual bool array(const std::function<bool(Deserializer*)>&) const = 0;
60
61 // field() calls the provided std::function for deserializing the field with
62 // the given name from the struct object referenced by this Deserializer.
63 virtual bool field(const std::string& name,
64 const std::function<bool(Deserializer*)>&) const = 0;
65
66 // deserialize() delegates to TypeOf<T>::type()->deserialize().
67 template <typename T,
68 typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
69 inline bool deserialize(T*) const;
70
71 // deserialize() decodes an array.
72 template <typename T>
73 inline bool deserialize(dap::array<T>*) const;
74
75 // deserialize() decodes an optional.
76 template <typename T>
77 inline bool deserialize(dap::optional<T>*) const;
78
79 // deserialize() decodes an variant.
80 template <typename T0, typename... Types>
81 inline bool deserialize(dap::variant<T0, Types...>*) const;
82
83 // deserialize() decodes the struct field f with the given name.
84 template <typename T>
85 inline bool field(const std::string& name, T* f) const;
86};
87
88template <typename T, typename>
89bool Deserializer::deserialize(T* ptr) const {
90 return TypeOf<T>::type()->deserialize(this, ptr);
91}
92
93template <typename T>
94bool Deserializer::deserialize(dap::array<T>* vec) const {
95 auto n = count();
96 vec->resize(n);
97 size_t i = 0;
98 if (!array([&](Deserializer* d) { return d->deserialize(&(*vec)[i++]); })) {
99 return false;
100 }
101 return true;
102}
103
104template <typename T>
105bool Deserializer::deserialize(dap::optional<T>* opt) const {
106 T v;
107 if (deserialize(&v)) {
108 *opt = v;
109 }
110 return true;
111}
112
113template <typename T0, typename... Types>
114bool Deserializer::deserialize(dap::variant<T0, Types...>* var) const {
115 return deserialize(&var->value);
116}
117
118template <typename T>
119bool Deserializer::field(const std::string& name, T* v) const {
120 return this->field(name,
121 [&](const Deserializer* d) { return d->deserialize(v); });
122}
123
124////////////////////////////////////////////////////////////////////////////////
125// Serializer
126////////////////////////////////////////////////////////////////////////////////
127class FieldSerializer;
128
129// Serializer is the interface used to encode data to structured storage.
130// A Serializer is associated with a single storage object, whos type and value
131// is assigned by a call to serialize().
132// If serialize() is called multiple times on the same Serializer instance,
133// the last type and value is stored.
134// Methods that return a bool use this to indicate success.
135class Serializer {
136 public:
137 virtual ~Serializer() = default;
138
139 // serialization methods for simple data types.
140 virtual bool serialize(boolean) = 0;
141 virtual bool serialize(integer) = 0;
142 virtual bool serialize(number) = 0;
143 virtual bool serialize(const string&) = 0;
144 virtual bool serialize(const dap::object&) = 0;
145 virtual bool serialize(const any&) = 0;
146
147 // array() encodes count array elements to the array object referenced by this
148 // Serializer. The std::function will be called count times, each time with a
149 // Serializer that should be used to encode the n'th array element's data.
150 virtual bool array(size_t count, const std::function<bool(Serializer*)>&) = 0;
151
152 // object() begins encoding the object referenced by this Serializer.
153 // The std::function will be called with a FieldSerializer to serialize the
154 // object's fields.
155 virtual bool object(const std::function<bool(dap::FieldSerializer*)>&) = 0;
156
157 // remove() deletes the object referenced by this Serializer.
158 // remove() can be used to serialize optionals with no value assigned.
159 virtual void remove() = 0;
160
161 // serialize() delegates to TypeOf<T>::type()->serialize().
162 template <typename T,
163 typename = std::enable_if<TypeOf<T>::has_custom_serialization>>
164 inline bool serialize(const T&);
165
166 // serialize() encodes the given array.
167 template <typename T>
168 inline bool serialize(const dap::array<T>&);
169
170 // serialize() encodes the given optional.
171 template <typename T>
172 inline bool serialize(const dap::optional<T>& v);
173
174 // serialize() encodes the given variant.
175 template <typename T0, typename... Types>
176 inline bool serialize(const dap::variant<T0, Types...>&);
177
178 // deserialize() encodes the given string.
179 inline bool serialize(const char* v);
180};
181
182template <typename T, typename>
183bool Serializer::serialize(const T& object) {
184 return TypeOf<T>::type()->serialize(this, &object);
185}
186
187template <typename T>
188bool Serializer::serialize(const dap::array<T>& vec) {
189 auto it = vec.begin();
190 return array(vec.size(), [&](Serializer* s) { return s->serialize(*it++); });
191}
192
193template <typename T>
194bool Serializer::serialize(const dap::optional<T>& opt) {
195 if (!opt.has_value()) {
196 remove();
197 return true;
198 }
199 return serialize(opt.value());
200}
201
202template <typename T0, typename... Types>
203bool Serializer::serialize(const dap::variant<T0, Types...>& var) {
204 return serialize(var.value);
205}
206
207bool Serializer::serialize(const char* v) {
208 return serialize(std::string(v));
209}
210
211////////////////////////////////////////////////////////////////////////////////
212// FieldSerializer
213////////////////////////////////////////////////////////////////////////////////
214
215// FieldSerializer is the interface used to serialize fields of an object.
216class FieldSerializer {
217 public:
218 using SerializeFunc = std::function<bool(Serializer*)>;
219 template <typename T>
220 using IsSerializeFunc = std::is_convertible<T, SerializeFunc>;
221
222 virtual ~FieldSerializer() = default;
223
224 // field() encodes a field to the struct object referenced by this Serializer.
225 // The SerializeFunc will be called with a Serializer used to encode the
226 // field's data.
227 virtual bool field(const std::string& name, const SerializeFunc&) = 0;
228
229 // field() encodes the field with the given name and value.
230 template <
231 typename T,
232 typename = typename std::enable_if<!IsSerializeFunc<T>::value>::type>
233 inline bool field(const std::string& name, const T& v);
234};
235
236template <typename T, typename>
237bool FieldSerializer::field(const std::string& name, const T& v) {
238 return this->field(name, [&](Serializer* s) { return s->serialize(v); });
239}
240
241} // namespace dap
242
243#endif // dap_serialization_h
244