Skip to content

cpplibv/vide

Repository files navigation

cpplibv/vide - A C++23 serialization library

Originally based on and forked from: USCiLab/cereal

Compared to the original project the most notable changes are: - Fixed numerous security vulnerability - Improved API flexibility and compossibility - Added features and utilities - Significantly improved compile time - Modernized and simplified the codebase Compared to USCiLab/cereal multiple core functionality has been changed and therefore the two are not compatible! As development is treated as experimental neither forward, nor backward compatibility is guaranteed (but the library is expected to reach a stable state soon.) Bugfixes from the upstream are planned to be ported manually (and currently in sync with 2024.05.02 d1fcec807).

Changes / Differences to Cereal:

  • Change name to vide to indicate the incompatibility with upstream
    • vide comes from latin word serial
    • Name change was necessary due to incompatibilities
  • Remove some legacy compiler support
  • Bump required versions to C++23, GCC 11.2, CMake 3.20
  • Fixes and breaks some minor stuff
  • Remove VIDE_SETUP_ARCHIVE_TRAITS (Input and output archives are no longer linked)
    • Pro: Enables archives to be template types
    • Pro: One less macro that has to be called
    • Pro: Allows single in or out direction archives or type supports
    • Con: load_minimal type deduction is now done with the input archives on the save_minimal function (never called, only instantiated for type deduction)
    • Con: No check if save_minimal and load_minimal are correctly using different types
    • Note: Cons could be negated with a single typedef inside the input archive to the output archive
  • New archive flag vide::IgnoreNVP: Add support for specifying if archives ignores name from NVPs (previously this was hardcoded for the built-in binary archive only)
  • Move NVP into its own header
  • Move vide::access into its own header and add access_fwd.hpp header for forward declaration only
  • Move BinaryData, SizeTag, MapItem and construct into their own header
  • Rework type serializers to only include what is required
  • Remove load_and_construct
  • Remove pointer to derived in archive bases (just use this with CRTP)
  • Make archives movable
  • Remove the experimental UserDataAdapter (A better solution will come)
  • Remove the ability to call the archives with multiple member at the same times as ar(member0, member1, member2). Chaining is still possible prefer that syntax ar(member0)(member1)(member2) or just use multiple calls
    • Pro: Enables some future shenanigans
    • Pro: Alternative syntax are more clear and has same number of character, and has better auto formatting
    • Pro: More clear evaluation order, less variadic template
    • Con: More breakage
  • Add proxy archives (A way to inject context information into the serialization chain)
    • NOTE: polymorphic serialization will fall back to the underlying archives and not use the proxy
  • Add process_as customization point for archives to handle special types
  • Remove prologue and epilogue function support (process_as can take care of it)
  • Add ar.nvp("var", var) syntax to allow option to not include any header file and rely on dependent names only
  • Bump version to 2.1.0 and start versioning Vide
  • Version 2.2.0:
    • Remove specialize/specialization feature that could disambiguate in duplicate serialization methods. (For now serialization methods consistency is required in inheritance hierarchies)
    • Remove string/arithmetic type restriction from load_minimal/save_minimal
    • Add support for const reference return type during minimal serialization
    • Add support for recursive minimal serialization (But it is recommended to only use it with primitive/trivial types)
  • Version 2.2.1:
    • Add support for move reference parameter type for load_minimal function
  • Version 2.3.0:
    • Breaking change: Serialized data format changed breaking compatibility with data generated before this version
    • Sync with upstream 2024.05.02 d1fcec807
    • Security: Fix vulnerability where invalid data could allocate unbounded amount of memory during deserialization
      • Add archive.safe_to_reserve() to check and clamp the amount of memory reserved
      • Add archive.validate_read_size() to check if the archive has enough data for binary deserialization
      • Add archive.maximumBinaryReadSize() to report how much data could be extracted during binary deserialization
    • Refactor and modernize type traits
    • Add archive.size_tag() as a dependent name for vide::make_size_tag
    • Add Archive::is_binary_archive
    • Add Archive::size_type as a dependent name for vide::size_type
    • Add Archive::supports_binary to test if the archive can binary serialize T
    • Remove Archive::could_serialize
    • Improve compile time performance
    • Improve and modernize meta programming practices and techniques
    • Improve archive.nvp() to respect IgnoreNVP flag
    • Cleanup compiler warnings
  • Version 2.4.0:
    • Security: Fix vulnerability where binary bool would allow loading non 0 or 1 as value which could result in UB
    • Add support for static member serialize_class_version-ing which is serialized regardless if it is used in serializers or not
    • Add VIDE_CLASS_VERSION_TAG_NAME as a customization macro for vide_class_version
    • Improve CMAKE_BUILD_TYPE to be case-insensitive
    • Rename VIDE_XML_STRING_VALUE to VIDE_XML_ROOT_TAG_NAME
    • Move out exception.hpp header from details
    • Remove compatibility operator>>, operator<< and operator&
  • Version 2.5.0:
    • Add enum value verifications system: If an 'enum value set' is specified it will be verified during serialization and deserialization. This feature resolves the last known security concern. The 'enum value set' can be specified for EnumType by:
      • Defining an enumerator serialize_unbounded inside the EnumType with any value. Valid values: every underlying representation.
      • Defining an enumerator serialize_end_value inside the EnumType with the max value. Valid values: [0..end_value).
      • Defining an enumerator serialize_max_value inside the EnumType with the max value. Valid values: [0..max_value].
      • Defining a free function serialize_enum_unbounded(EnumType) : void reachable by ADL. Valid values every underlying representation.
      • Defining a free function serialize_enum_end_value(EnumType) : EnumType reachable by ADL returning the max value. Valid values: [0..end_value).
      • Defining a free function serialize_enum_end_value(EnumType) : Underlying reachable by ADL returning the max value. Valid values: [0..end_value).
      • Defining a free function serialize_enum_max_value(EnumType) : EnumType reachable by ADL returning with the max value. Valid values: [0..max_value].
      • Defining a free function serialize_enum_max_value(EnumType) : Underlying reachable by ADL returning with the max value. Valid values: [0..max_value].
      • Defining a free function serialize_enum_verify(EnumType) : bool reachable by ADL returning the value's validity. Valid values will those which return true.
      • As soon as C++ reflection are implemented additional (better) definition ways will be added
    • Add VIDE_STRICT_ENUM_VALUE_SET macro to specify whether vide should enforce enum value set specification. Should be defined to 0 or 1. Defaults to (0) disabled.
    • Add static_assert message for incomplete types
    • Add archive.ignore<T>() and archive.nvp_ignore<T>(name) to load and discard a value from an input archive. Does nothing for output archives. Useful for ignoring variables from data serialized by old versions.
      template <class Archive> void serialize(Archive& ar, uint32_t version) {
          if (version < 2) {
              ar.template nvp_ignore<int>("removedVarNamed");
              ar.template nvp_ignore<int>(); // removedVarUnnamed
          }
      }
    • Add archive.load<T>() : T and archive.nvp_load<T>(name) : T to direct load a value from an input archive. Does not exist for output archives. Useful shorthand if the deserialized value is not directly assigned to a final object.
      template <class Archive> void serialize(Archive& ar, uint32_t version) {
          if constexpr (Archive::is_input) {
              var0 = ar.template nvp_load<int>("var0") * 100;
              var1 = ar.template nvp_load<int>() * 100;
          } else {
              ar(var0 / 100);
              ar(var1 / 100);
          }
      }
    • Add API for value validations:
      • archive.operator(), archive.nvp, archive.load, archive.nvp_load, archive.ignore, archive.nvp_ignore now accepts a variadic set of validation objects.
      • archive.verify(bool, string) can be used to throw exception if the is enforcing validation.
      • vide::notnull or archive.notnull: A var bool testing validation object.
      • vide::notempty or archive.notempty: A !var.empty() testing validation object.
      • vide::maxsize(limit) or archive.maxsize(limit): A var.size() <= limit testing validation object.
      • Proxy archives can opt-out of validation tests with declaring a static constexpr bool enforce_validation = false; member.
    • Sync with upstream 2025.01.20 a56bad8bb
    • Sync, review and merge most upstream PRs up until 2025.09.14 872
    • Update RapidJSON and RapidXML

Planned:

  • TODO: Customization point for smart pointers
  • Foreach iteration/visitor algorithms
  • An alternative for load_minimal/save_minimal syntax with T& serialize_transparent() which does them in a single step
  • Further improved compile time performance (by organizing includes)
  • Scoped versions and version guards: const auto version_guard = ar.scope_version(config_version); and ar.scope_version()
  • Maybe: Context variables passed as additional function arguments
  • Maybe: Versioned<->type selector
  • Maybe: Patch back location. A way to skip some bytes and write (patch) back the desired values later
    const auto index_body_a_loc = ar.patch<uint32_t>();
    ar(header);
    const auto body_a_offset = ar.tellp();
    ar(body_a);
    ar(index_body_a_loc, body_a_offset);
    
  • (Preliminary) Version 3.0.0:
    • Major breaking change in the serialized archives (expected to be the last)

cereal - A C++11 library for serialization

cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.

cereal has great documentation

Looking for more information on how cereal works and its documentation? Visit cereal's web page to get the latest information.

cereal is easy to use

Installation and use of of cereal is fully documented on the main web page, but this is a quick and dirty version:

  • Download cereal and place the headers somewhere your code can see them
  • Write serialization functions for your custom types or use the built in support for the standard library cereal provides
  • Use the serialization archives to load and save data
#include <vide/types/unordered_map.hpp>
#include <vide/types/memory.hpp>
#include <vide/archives/binary.hpp>
#include <fstream>

struct MyRecord {
	uint8_t x, y;
	float z;

	template <class Archive>
	void serialize(Archive& ar) {
		ar(x);
		ar(y);
		ar(z);
	}
};

struct SomeData {
	int32_t id;
	std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;

	template <class Archive>
	void save(Archive& ar) const {
		ar(data);
	}

	template <class Archive>
	void load(Archive& ar) {
		static int32_t idGen = 0;
		id = idGen++;
		ar(data);
	}
};

int main() {
	std::ofstream os("out.bin", std::ios::binary | std::ios::out);

	SomeData myData;
	{
		vide::BinaryOutputArchive archive(os);
		archive(myData);
	}

	return 0;
}

cereal has a mailing list

Either get in touch over email or on the web.

cereal has a permissive license

cereal is licensed under the BSD license.

cereal build status

  • master : Build Status Build status

Were you looking for the Haskell cereal? Go here.

About

A C++23 library for serialization

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 54

Languages