| // Copyright 2019 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #ifndef dap_serialization_h | |
| #define dap_serialization_h | |
| #include "typeof.h" | |
| #include "types.h" | |
| #include <cstddef> // ptrdiff_t | |
| #include <type_traits> | |
| namespace dap { | |
| // Field describes a single field of a struct. | |
| struct Field { | |
| std::string name; // name of the field | |
| ptrdiff_t offset; // offset of the field to the base of the struct | |
| const TypeInfo* type; // type of the field | |
| }; | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // Deserializer | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // Deserializer is the interface used to decode data from structured storage. | |
| // Methods that return a bool use this to indicate success. | |
| class Deserializer { | |
| public: | |
| virtual ~Deserializer() = default; | |
| // deserialization methods for simple data types. | |
| // If the stored object is not of the correct type, then these function will | |
| // return false. | |
| virtual bool deserialize(boolean*) const = 0; | |
| virtual bool deserialize(integer*) const = 0; | |
| virtual bool deserialize(number*) const = 0; | |
| virtual bool deserialize(string*) const = 0; | |
| virtual bool deserialize(object*) const = 0; | |
| virtual bool deserialize(any*) const = 0; | |
| // count() returns the number of elements in the array object referenced by | |
| // this Deserializer. | |
| virtual size_t count() const = 0; | |
| // array() calls the provided std::function for deserializing each array | |
| // element in the array object referenced by this Deserializer. | |
| virtual bool array(const std::function<bool(Deserializer*)>&) const = 0; | |
| // field() calls the provided std::function for deserializing the field with | |
| // the given name from the struct object referenced by this Deserializer. | |
| virtual bool field(const std::string& name, | |
| const std::function<bool(Deserializer*)>&) const = 0; | |
| // deserialize() delegates to TypeOf<T>::type()->deserialize(). | |
| template <typename T, | |
| typename = std::enable_if<TypeOf<T>::has_custom_serialization>> | |
| inline bool deserialize(T*) const; | |
| // deserialize() decodes an array. | |
| template <typename T> | |
| inline bool deserialize(dap::array<T>*) const; | |
| // deserialize() decodes an optional. | |
| template <typename T> | |
| inline bool deserialize(dap::optional<T>*) const; | |
| // deserialize() decodes an variant. | |
| template <typename T0, typename... Types> | |
| inline bool deserialize(dap::variant<T0, Types...>*) const; | |
| // deserialize() decodes the struct field f with the given name. | |
| template <typename T> | |
| inline bool field(const std::string& name, T* f) const; | |
| }; | |
| template <typename T, typename> | |
| bool Deserializer::deserialize(T* ptr) const { | |
| return TypeOf<T>::type()->deserialize(this, ptr); | |
| } | |
| template <typename T> | |
| bool Deserializer::deserialize(dap::array<T>* vec) const { | |
| auto n = count(); | |
| vec->resize(n); | |
| size_t i = 0; | |
| if (!array([&](Deserializer* d) { return d->deserialize(&(*vec)[i++]); })) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| template <typename T> | |
| bool Deserializer::deserialize(dap::optional<T>* opt) const { | |
| T v; | |
| if (deserialize(&v)) { | |
| *opt = v; | |
| } | |
| return true; | |
| } | |
| template <typename T0, typename... Types> | |
| bool Deserializer::deserialize(dap::variant<T0, Types...>* var) const { | |
| return deserialize(&var->value); | |
| } | |
| template <typename T> | |
| bool Deserializer::field(const std::string& name, T* v) const { | |
| return this->field(name, | |
| [&](const Deserializer* d) { return d->deserialize(v); }); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // Serializer | |
| //////////////////////////////////////////////////////////////////////////////// | |
| class FieldSerializer; | |
| // Serializer is the interface used to encode data to structured storage. | |
| // A Serializer is associated with a single storage object, whos type and value | |
| // is assigned by a call to serialize(). | |
| // If serialize() is called multiple times on the same Serializer instance, | |
| // the last type and value is stored. | |
| // Methods that return a bool use this to indicate success. | |
| class Serializer { | |
| public: | |
| virtual ~Serializer() = default; | |
| // serialization methods for simple data types. | |
| virtual bool serialize(boolean) = 0; | |
| virtual bool serialize(integer) = 0; | |
| virtual bool serialize(number) = 0; | |
| virtual bool serialize(const string&) = 0; | |
| virtual bool serialize(const dap::object&) = 0; | |
| virtual bool serialize(const any&) = 0; | |
| // array() encodes count array elements to the array object referenced by this | |
| // Serializer. The std::function will be called count times, each time with a | |
| // Serializer that should be used to encode the n'th array element's data. | |
| virtual bool array(size_t count, const std::function<bool(Serializer*)>&) = 0; | |
| // object() begins encoding the object referenced by this Serializer. | |
| // The std::function will be called with a FieldSerializer to serialize the | |
| // object's fields. | |
| virtual bool object(const std::function<bool(dap::FieldSerializer*)>&) = 0; | |
| // remove() deletes the object referenced by this Serializer. | |
| // remove() can be used to serialize optionals with no value assigned. | |
| virtual void remove() = 0; | |
| // serialize() delegates to TypeOf<T>::type()->serialize(). | |
| template <typename T, | |
| typename = std::enable_if<TypeOf<T>::has_custom_serialization>> | |
| inline bool serialize(const T&); | |
| // serialize() encodes the given array. | |
| template <typename T> | |
| inline bool serialize(const dap::array<T>&); | |
| // serialize() encodes the given optional. | |
| template <typename T> | |
| inline bool serialize(const dap::optional<T>& v); | |
| // serialize() encodes the given variant. | |
| template <typename T0, typename... Types> | |
| inline bool serialize(const dap::variant<T0, Types...>&); | |
| // deserialize() encodes the given string. | |
| inline bool serialize(const char* v); | |
| protected: | |
| static inline const TypeInfo* get_any_type(const any&); | |
| static inline const void* get_any_val(const any&); | |
| }; | |
| inline const TypeInfo* Serializer::get_any_type(const any& a){ | |
| return a.type; | |
| } | |
| const void* Serializer::get_any_val(const any& a) { | |
| return a.value; | |
| } | |
| template <typename T, typename> | |
| bool Serializer::serialize(const T& object) { | |
| return TypeOf<T>::type()->serialize(this, &object); | |
| } | |
| template <typename T> | |
| bool Serializer::serialize(const dap::array<T>& vec) { | |
| auto it = vec.begin(); | |
| return array(vec.size(), [&](Serializer* s) { return s->serialize(*it++); }); | |
| } | |
| template <typename T> | |
| bool Serializer::serialize(const dap::optional<T>& opt) { | |
| if (!opt.has_value()) { | |
| remove(); | |
| return true; | |
| } | |
| return serialize(opt.value()); | |
| } | |
| template <typename T0, typename... Types> | |
| bool Serializer::serialize(const dap::variant<T0, Types...>& var) { | |
| return serialize(var.value); | |
| } | |
| bool Serializer::serialize(const char* v) { | |
| return serialize(std::string(v)); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // FieldSerializer | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // FieldSerializer is the interface used to serialize fields of an object. | |
| class FieldSerializer { | |
| public: | |
| using SerializeFunc = std::function<bool(Serializer*)>; | |
| template <typename T> | |
| using IsSerializeFunc = std::is_convertible<T, SerializeFunc>; | |
| virtual ~FieldSerializer() = default; | |
| // field() encodes a field to the struct object referenced by this Serializer. | |
| // The SerializeFunc will be called with a Serializer used to encode the | |
| // field's data. | |
| virtual bool field(const std::string& name, const SerializeFunc&) = 0; | |
| // field() encodes the field with the given name and value. | |
| template < | |
| typename T, | |
| typename = typename std::enable_if<!IsSerializeFunc<T>::value>::type> | |
| inline bool field(const std::string& name, const T& v); | |
| }; | |
| template <typename T, typename> | |
| bool FieldSerializer::field(const std::string& name, const T& v) { | |
| return this->field(name, [&](Serializer* s) { return s->serialize(v); }); | |
| } | |
| } // namespace dap | |
| #endif // dap_serialization_h |