mysql-server/libs/mysql/serialization/archive.h
2025-03-05 14:31:37 +07:00

204 lines
8.2 KiB
C++

// 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.
#ifndef MYSQL_SERIALIZATION_ARCHIVE_H
#define MYSQL_SERIALIZATION_ARCHIVE_H
#include "mysql/serialization/field_wrapper.h"
#include "mysql/serialization/serialization_error.h"
#include "mysql/serialization/serialization_types.h"
/// @file
/// Experimental API header
/// @addtogroup GroupLibsMysqlSerialization
/// @{
namespace mysql::serialization {
/// @brief Interface for archives (file archive, byte vector archive,
/// string archive etc.), available only to instances implementing Serializable
/// interface and Archive interface
/// @details Archive is responsible for primitive types byte-level formatting
/// and data storage. It also provides implementation of separation between
/// serializable types, serializable type fields, separate entries in
/// containers (repeated fields). Derived class should implement
/// all methods of provided interface (except methods for error handling).
/// @tparam Archive_derived_type Archive derived that is implementing Archive
/// interface (CRTP)
template <class Archive_derived_type>
class Archive {
public:
/// @brief Ingests argument into this archive
/// @tparam Type type of the argument
/// @param [in] arg Argument to read data from
/// @return This archive reference
/// @note To be implemented in Archive_derived_type
template <typename Type>
Archive_derived_type &operator<<(Type &&arg) {
return get_derived()->operator<<(std::forward<Type>(arg));
}
/// @brief Reads argument from this archive
/// @tparam Type type of the argument
/// @param [in] arg Argument to store data into
/// @return This archive reference
/// @note To be implemented in Archive_derived_type
template <typename Type>
Archive_derived_type &operator>>(Type &&arg) {
return get_derived()->operator>>(std::forward<Type>(arg));
}
/// @brief Function for the API user to access data in the archive
/// @returns Archive data, defined in the Archive (e.g. pointer to bytes ...)
/// @note To be implemented in Archive_derived_type
decltype(auto) get_raw_data() { return get_derived()->get_raw_data(); }
/// @brief Function returns size of serialized argument
/// @tparam Type type of the argument
/// @param [in] arg serialized argument
/// @return size of serialized argument
/// @note To be implemented in Archive_derived_type
template <typename Type>
static std::size_t get_size(Type &&arg) {
return Archive_derived_type::get_size(std::forward<Type>(arg));
}
/// @brief Returns archive size - size of data written to the archive
/// @return archive size - size of data written to the archive
/// @note To be implemented in Archive_derived_type
inline std::size_t get_size_written() const {
return Archive_derived_type::get_size_written();
}
/// @brief Function returns maximum size of the Type
/// @tparam Type serialized type
/// @return maximum size of the Type in the stream
/// @note To be implemented in Archive_derived_type
template <typename Type>
static constexpr std::size_t get_max_size() {
return Archive_derived_type::template get_max_size<Type>();
}
// used to access the protected API of an archive (peek/seek_to/error methods)
// by any implementation of a Serializer class
template <class Serializer_derived_current_type, class Archive_current_type>
friend class Serializer;
// available for serializers
/// @brief This method needs to define field separator to be inserted
/// after the field, note that some formats won't contain separators
/// Used mainly for text formatters
/// @details Field is defined a a single field in object of serializable class
// which is identified by an unique id within this object
virtual void put_field_separator() {}
/// @brief This method needs to define field entry separator to be inserted
/// after the field entry, note that some formats won't contain separators
/// Used mainly for text formatters
/// @details Each field may have a several entries (e.g. vector)
virtual void put_entry_separator() {}
/// @brief This method needs to define level separator to be inserted
/// after the level, note that some formats won't contain separators
/// Used mainly for text formatters
/// @details Each field that is an object of serializable class creates a new
/// level
virtual void put_level_separator() {}
/// @brief This method needs to define how to process field separator during
/// decoding. Used mainly for text formatters
/// @details Field is defined a a single field in object of serializable class
// which is identified by an unique id within this object
virtual void process_field_separator() {}
/// @brief This method needs to define how to process field entry separator
/// during decoding. Used mainly for text formatters
/// @details Each field may have a several entries (e.g. vector)
virtual void process_entry_separator() {}
/// @brief This method needs to define how to process level separator during
/// decoding. Used mainly for text formatters
/// @details Each field that is an object of serializable class creates a new
/// level
virtual void process_level_separator() {}
protected:
/// @brief Casts this to derived type
/// @return Derived class pointer to this
/// @note To be implemented in Archive_derived_type
const Archive_derived_type *get_derived_const() {
return static_cast<const Archive_derived_type *>(this);
}
/// @brief Casts this to derived type
/// @return Derived class pointer to this
/// @note To be implemented in Archive_derived_type
Archive_derived_type *get_derived() {
return static_cast<Archive_derived_type *>(this);
}
/// @brief This method decodes field id, without moving stream positions
/// @returns Serialized field id
/// @note To be implemented in Archive_derived_type
Field_id_type peek_type_field_id() {
return get_derived()->peek_type_field_id();
}
/// @brief Peeks selected field wrapper (reads data without updating
/// read stream position)
/// @note To be implemented in Archive_derived_type
template <class Field_type>
void peek(Field_type &&field) {
return get_derived()->peek(std::forward<Field_type>(field));
}
/// @brief Moves the current read position to current position + size
/// @param[in] num_pos Number of positions to be skipped
/// @note To be implemented in Archive_derived_type
void seek_to(std::size_t num_pos) { get_derived()->seek_to(num_pos); }
/// @brief Gets current read pos
/// @return Current read pos
/// @note To be implemented in Archive_derived_type
std::size_t get_read_pos() const {
return get_derived_const()->get_read_pos();
}
bool is_error() const { return m_error.is_error(); }
bool is_good() const { return !m_error.is_error(); }
const Serialization_error &get_error() { return m_error; }
void clear_error() { m_error = Serialization_error(); }
/// @brief Destructor
/// @note Cannot create an object of 'abstract' Archive type
virtual ~Archive() = default;
Serialization_error m_error; ///< Holds information about error
};
} // namespace mysql::serialization
/// @}
#endif // MYSQL_SERIALIZATION_ARCHIVE_H