// 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 // ptrdiff_t #include 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&) 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&) const = 0; // deserialize() delegates to TypeOf::type()->deserialize(). template ::has_custom_serialization>> inline bool deserialize(T*) const; // deserialize() decodes an array. template inline bool deserialize(dap::array*) const; // deserialize() decodes an optional. template inline bool deserialize(dap::optional*) const; // deserialize() decodes an variant. template inline bool deserialize(dap::variant*) const; // deserialize() decodes the struct field f with the given name. template inline bool field(const std::string& name, T* f) const; }; template bool Deserializer::deserialize(T* ptr) const { return TypeOf::type()->deserialize(this, ptr); } template bool Deserializer::deserialize(dap::array* 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 bool Deserializer::deserialize(dap::optional* opt) const { T v; if (deserialize(&v)) { *opt = v; } return true; } template bool Deserializer::deserialize(dap::variant* var) const { return deserialize(&var->value); } template 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&) = 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&) = 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::type()->serialize(). template ::has_custom_serialization>> inline bool serialize(const T&); // serialize() encodes the given array. template inline bool serialize(const dap::array&); // serialize() encodes the given optional. template inline bool serialize(const dap::optional& v); // serialize() encodes the given variant. template inline bool serialize(const dap::variant&); // 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 bool Serializer::serialize(const T& object) { return TypeOf::type()->serialize(this, &object); } template bool Serializer::serialize(const dap::array& vec) { auto it = vec.begin(); return array(vec.size(), [&](Serializer* s) { return s->serialize(*it++); }); } template bool Serializer::serialize(const dap::optional& opt) { if (!opt.has_value()) { remove(); return true; } return serialize(opt.value()); } template bool Serializer::serialize(const dap::variant& 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; template using IsSerializeFunc = std::is_convertible; 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::value>::type> inline bool field(const std::string& name, const T& v); }; template 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