// Copyright (c) 2023, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, // as published by the Free Software Foundation. // // This program is designed to work with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license // documentation. The authors of MySQL hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have either included with // the program or referenced in the documentation. // // This program 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, version 2.0, for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. /// @file /// Experimental API header #include namespace mysql::serialization { template template void Serializer::encode_field( Level_type level, Field_id_type field_id, const Field_definition &field_definition) { get_derived()->encode(level, field_id, field_definition); } template template void Serializer::decode_field( Level_type level, Field_id_type field_id, std::size_t serializable_end_pos, Field_definition &field_definition) { get_derived()->decode(level, field_id, serializable_end_pos, field_definition); } template template std::size_t Serializer::get_size_field_def( Field_id_type field_id, const Field_definition &field_definition) { return Serializer_derived_type::template get_size_field_def(field_id, field_definition); } template template std::size_t Serializer::get_size_serializable( Field_id_type field_id, const Serializable_concrete_type &serializable, bool skip_id) { return Serializer_derived_type::template get_size_serializable( field_id, serializable, skip_id); } template template std::size_t Serializer::get_size( const T &arg) { return get_size_serializable(0, arg, false); } template template Serializer & Serializer::operator<<(const T &arg) { Field_id_type field_id = serialization_format_version; encode_serializable(m_level, field_id, arg, false); return *this; } template template Serializer &Serializer::operator>>(T &arg) { Field_id_type field_id = serialization_format_version; // passing 0 as serializable_end_pos decode_serializable(m_level, field_id, 0, arg, false); return *this; } template Archive_type &Serializer::get_archive() { return m_archive; } template template void Serializer:: encode_serializable_fields(const Serializable_type &serializable, Level_type level) { auto process_serializable = [ this, level ](const auto &field, auto field_id) -> auto { this->encode_serializable(level, field_id, field, false); }; auto process_field = [ this, level ](const auto &field, auto field_id) -> auto { this->encode_field(level, field_id, field); ++field_id; }; serializable.do_for_each_field(process_serializable, process_field); } template template void Serializer::encode_serializable( Level_type level, Field_id_type field_id, const Serializable_type &serializable, bool skip_id) { if (is_good()) { get_derived()->encode_serializable_metadata(level, field_id, serializable, skip_id); if (is_error()) { return; } // restart numbering below for nested type // separate enumeration is needed to keep forward compatibility of // serialized types, this way if a field is added inside a nested type, // it does not affect rest of the class fields ids (they keep the same // numbering). Before restarting, serializable must save it's own id encode_serializable_fields(serializable, level + 1); } } template template void Serializer:: decode_serializable_fields(Serializable_type &serializable, Level_type level, std::size_t serializable_end_pos) { auto process_serializable = [ this, level, serializable_end_pos ]( auto &field, auto field_id) -> auto { this->decode_serializable(level, field_id, serializable_end_pos, field, false); }; auto process_field = [ this, level, serializable_end_pos ]( auto &field, auto field_id) -> auto { this->decode_field(level, field_id, serializable_end_pos, field); ++field_id; }; serializable.do_for_each_field(process_serializable, process_field); } template template void Serializer::decode_serializable( Level_type level, Field_id_type field_id, std::size_t serializable_end_pos, Serializable_type &serializable, bool skip_id) { // serializable_end_pos = 0 is a marker for serializers that don't check end // position and for the top-level serializable field (no parent serializable // with end position defined) if (skip_id == false && serializable_end_pos != 0 && m_archive.get_read_pos() == serializable_end_pos) { // reached the end // missing field handling here // must run field missing functors for all serializable fields recursively auto run_field_missing_functor = [](auto &field, auto) { field.run_field_missing(); }; auto serializable_field_missing_functor = [](auto &, auto) {}; serializable.do_for_each_field(serializable_field_missing_functor, run_field_missing_functor); return; } if (is_good()) { auto curr_pos = m_archive.get_read_pos(); auto encoded_size_read = get_derived()->decode_serializable_metadata( level, field_id, serializable, skip_id); if (is_error()) { return; } // restart numbering below for nested type // separate enumeration is needed to keep forward compatibility of // serialized types, this way if a field is added inside a nested type, // it does not affect rest of the class fields ids (they keep the same // numbering). Before restarting, serializable must save it's own id decode_serializable_fields(serializable, level + 1, curr_pos + encoded_size_read); auto next_pos = m_archive.get_read_pos(); auto expected_pos = curr_pos + encoded_size_read; if (expected_pos > next_pos && is_good()) { m_archive.seek_to(expected_pos - next_pos); } } } } // namespace mysql::serialization