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 | |
24 | namespace dap { |
25 | |
26 | // Field describes a single field of a struct. |
27 | struct 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. |
39 | class 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 | |
88 | template <typename T, typename> |
89 | bool Deserializer::deserialize(T* ptr) const { |
90 | return TypeOf<T>::type()->deserialize(this, ptr); |
91 | } |
92 | |
93 | template <typename T> |
94 | bool 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 | |
104 | template <typename T> |
105 | bool Deserializer::deserialize(dap::optional<T>* opt) const { |
106 | T v; |
107 | if (deserialize(&v)) { |
108 | *opt = v; |
109 | } |
110 | return true; |
111 | } |
112 | |
113 | template <typename T0, typename... Types> |
114 | bool Deserializer::deserialize(dap::variant<T0, Types...>* var) const { |
115 | return deserialize(&var->value); |
116 | } |
117 | |
118 | template <typename T> |
119 | bool 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 | //////////////////////////////////////////////////////////////////////////////// |
127 | class 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. |
135 | class 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 | |
182 | template <typename T, typename> |
183 | bool Serializer::serialize(const T& object) { |
184 | return TypeOf<T>::type()->serialize(this, &object); |
185 | } |
186 | |
187 | template <typename T> |
188 | bool 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 | |
193 | template <typename T> |
194 | bool 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 | |
202 | template <typename T0, typename... Types> |
203 | bool Serializer::serialize(const dap::variant<T0, Types...>& var) { |
204 | return serialize(var.value); |
205 | } |
206 | |
207 | bool 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. |
216 | class 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 | |
236 | template <typename T, typename> |
237 | bool 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 | |