/* * Copyright 2015 Cloudius Systems */ /* * This file is part of Scylla. * * Scylla is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Scylla is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scylla. If not, see . */ #ifndef DB_SERIALIZER_HH_ #define DB_SERIALIZER_HH_ #include #include "utils/data_input.hh" #include "utils/data_output.hh" #include "bytes_ostream.hh" #include "bytes.hh" #include "database_fwd.hh" #include "db/commitlog/replay_position.hh" namespace db { /** * Serialization objects for various types and using "internal" format. (Not CQL, origin whatnot). * The design rationale is that a "serializer" can be instantiated for an object, and will contain * the obj + size, and is usable as a functor. * * Serialization can also be done "explicitly" through the static method "write" * (Not using "serialize", because writing "serializer::serialize" all the time is tiring and redundant) * though care should be takes than data will fit of course. */ template class serializer { public: typedef T type; typedef data_output output; typedef data_input input; typedef serializer _MyType; serializer(const type&); // apply to memory, must be at least size() large. const _MyType& operator()(output& out) const { write(out, _item); return *this; } static void write(output&, const type&); static void read(type&, input&); static type read(input&); static void skip(input& in); size_t size() const { return _size; } void write(bytes_ostream& out) const { auto buf = out.write_place_holder(_size); data_output data_out((char*)buf, _size); write(data_out, _item); } void write(data_output& out) const { write(out, _item); } bytes to_bytes() const { bytes b(bytes::initialized_later(), _size); data_output out(b); write(out); return b; } static type from_bytes(bytes_view v) { data_input in(v); return read(in); } private: const type& _item; size_t _size; }; template class serializer> { public: typedef std::experimental::optional type; typedef data_output output; typedef data_input input; typedef serializer _MyType; serializer(const type& t) : _item(t) , _size(output::serialized_size() + (t ? serializer(*t).size() : 0)) {} // apply to memory, must be at least size() large. const _MyType& operator()(output& out) const { write(out, _item); return *this; } static void write(output& out, const type& v) { bool en = v; out.write(en); if (en) { serializer::write(out, *v); } } static void read(type& dst, input& in) { auto en = in.read(); if (en) { dst = serializer::read(in); } else { dst = {}; } } static type read(input& in) { type t; read(t, in); return t; } static void skip(input& in) { auto en = in.read(); if (en) { serializer::skip(in); } } size_t size() const { return _size; } void write(bytes_ostream& out) const { auto buf = out.write_place_holder(_size); data_output data_out((char*)buf, _size); write(data_out, _item); } void write(data_output& out) const { write(out, _item); } bytes to_bytes() const { bytes b(bytes::initialized_later(), _size); data_output out(b); write(out); return b; } static type from_bytes(bytes_view v) { data_input in(v); return read(in); } private: const std::experimental::optional _item; size_t _size; }; template<> serializer::serializer(const utils::UUID &); template<> void serializer::write(output&, const type&); template<> void serializer::read(utils::UUID&, input&); template<> void serializer::skip(input&); template<> utils::UUID serializer::read(input&); template<> serializer::serializer(const bytes &); template<> void serializer::write(output&, const type&); template<> void serializer::read(bytes&, input&); template<> void serializer::skip(input&); template<> serializer::serializer(const bytes_view&); template<> void serializer::write(output&, const type&); template<> void serializer::read(bytes_view&, input&); template<> bytes_view serializer::read(input&); template<> serializer::serializer(const sstring&); template<> void serializer::write(output&, const type&); template<> void serializer::read(sstring&, input&); template<> void serializer::skip(input&); template<> serializer::serializer(const tombstone &); template<> void serializer::write(output&, const type&); template<> void serializer::read(tombstone&, input&); template<> serializer::serializer(const atomic_cell_view &); template<> void serializer::write(output&, const type&); template<> void serializer::read(atomic_cell_view&, input&); template<> atomic_cell_view serializer::read(input&); template<> serializer::serializer(const collection_mutation_view &); template<> void serializer::write(output&, const type&); template<> void serializer::read(collection_mutation_view&, input&); template<> serializer::serializer(const db::replay_position&); template<> void serializer::write(output&, const db::replay_position&); template<> void serializer::read(db::replay_position&, input&); template T serializer::read(input& in) { type t; read(t, in); return t; } extern template class serializer; extern template class serializer; extern template class serializer; extern template class serializer; extern template class serializer; extern template class serializer; typedef serializer tombstone_serializer; typedef serializer bytes_serializer; // Compatible with bytes_view_serializer typedef serializer bytes_view_serializer; // Compatible with bytes_serializer typedef serializer sstring_serializer; typedef serializer atomic_cell_view_serializer; typedef serializer collection_mutation_view_serializer; typedef serializer uuid_serializer; typedef serializer replay_position_serializer; } #endif /* DB_SERIALIZER_HH_ */