diff --git a/CHANGELOG.md b/CHANGELOG.md index 81afaa8..53a81ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [4.6.1](https://github.com/fraillt/bitsery/compare/v4.6.0...v4.6.1) (2019-06-27) + +### Features +* flexible syntax now also supports `cereal` like serialization interface (thanks to [Luli2020](https://github.com/Luli2020)) + +### Bug fixes +* when using `enableBitPacking`, internal context (i.e. context()) in serializer/deserializer was not copied to/from new bitpacking enabled instance. + # [4.6.0](https://github.com/fraillt/bitsery/compare/v4.5.1...v4.6.0) (2019-03-12) ### Features diff --git a/CMakeLists.txt b/CMakeLists.txt index 8125a28..371edbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.1) project(bitsery LANGUAGES CXX - VERSION 4.6.0) + VERSION 4.6.1) #======== build options =================================== option(BITSERY_BUILD_EXAMPLES "Build examples" OFF) diff --git a/doc/README.md b/doc/README.md index 363e16e..7780e57 100644 --- a/doc/README.md +++ b/doc/README.md @@ -15,7 +15,9 @@ Library design: Core Serializer/Deserializer functions (alphabetical order): +* `operator()` (4.6.1) (when flexible syntax is enabled) * `align` (1.0.0) +* `archive` (4.0.0) (when flexible syntax is enabled) * `boolValue` (4.0.0) * `container` (1.0.0) * `ext` (2.0.0) diff --git a/examples/flexible_syntax.cpp b/examples/flexible_syntax.cpp index a89c3ab..359e01a 100644 --- a/examples/flexible_syntax.cpp +++ b/examples/flexible_syntax.cpp @@ -19,11 +19,12 @@ struct MyStruct { void serialize(S& s) { //now we can use flexible syntax with s.archive(i, e, fs); + // flexible syntax also supports `cereal` like serialization interface by calling operator() + // s(i, e, fs); } }; - using namespace bitsery; //some helper types diff --git a/include/bitsery/adapter_reader.h b/include/bitsery/adapter_reader.h index f559257..8a2c9bf 100644 --- a/include/bitsery/adapter_reader.h +++ b/include/bitsery/adapter_reader.h @@ -258,6 +258,20 @@ namespace bitsery { } }; + + namespace details { + // used in "making friends" with non-wrapped deserializer type + template + struct GetNonWrappedAdapterReader { + using Reader = TReader; + }; + + template + struct GetNonWrappedAdapterReader> { + using Reader = TWrapped; + }; + } + } #endif //BITSERY_ADAPTER_READER_H diff --git a/include/bitsery/adapter_writer.h b/include/bitsery/adapter_writer.h index 42df5f0..94854c8 100644 --- a/include/bitsery/adapter_writer.h +++ b/include/bitsery/adapter_writer.h @@ -330,6 +330,19 @@ namespace bitsery { TWriter& _writer; }; + + namespace details { + // used in "making friends" with non-wrapped serializer type + template + struct GetNonWrappedAdapterWriter { + using Writer = TWriter; + }; + + template + struct GetNonWrappedAdapterWriter> { + using Writer = TWrapped; + }; + } } #endif //BITSERY_ADAPTER_WRITER_H diff --git a/include/bitsery/bitsery.h b/include/bitsery/bitsery.h index 7c6000d..1407f64 100644 --- a/include/bitsery/bitsery.h +++ b/include/bitsery/bitsery.h @@ -26,7 +26,7 @@ #define BITSERY_MAJOR_VERSION 4 #define BITSERY_MINOR_VERSION 6 -#define BITSERY_PATCH_VERSION 0 +#define BITSERY_PATCH_VERSION 1 #define BITSERY_QUOTE_MACRO(name) #name #define BITSERY_BUILD_VERSION_STR(major,minor, patch) \ diff --git a/include/bitsery/deserializer.h b/include/bitsery/deserializer.h index d93a500..34961a3 100644 --- a/include/bitsery/deserializer.h +++ b/include/bitsery/deserializer.h @@ -104,9 +104,7 @@ namespace bitsery { template BasicDeserializer &operator()(T &&head, TArgs &&... tail) { - //serialize object details::ArchiveFunction::invoke(*this, std::forward(head)); - //expand other elements archive(std::forward(tail)...); return *this; } @@ -340,6 +338,8 @@ namespace bitsery { private: friend AdapterAccess; + // this is required when creating bitpacking serializer, to access internal context + friend class BasicDeserializer::Reader, TContext>; TAdapterReader _reader; TContext* _context; @@ -415,7 +415,10 @@ namespace bitsery { void procEnableBitPacking(const Fnc& fnc, std::false_type) { //create serializer using bitpacking wrapper BPEnabledType tmp(_reader, _context); + // move internal context to and from of bitpacking enabled serializer + tmp._internalContext = std::move(_internalContext); fnc(tmp); + _internalContext = std::move(tmp._internalContext); } //these are dummy functions for extensions that have TValue = void diff --git a/include/bitsery/serializer.h b/include/bitsery/serializer.h index e6ee9d7..3e001fa 100644 --- a/include/bitsery/serializer.h +++ b/include/bitsery/serializer.h @@ -335,11 +335,14 @@ namespace bitsery { private: friend AdapterAccess; + // this is required when creating bitpacking serializer, to access internal context + friend class BasicSerializer::Writer, TContext>; TAdapterWriter _writer; TContext* _context; typename TWriter::TConfig::InternalContext _internalContext; + //process value types //false_type means that we must process all elements individually template @@ -404,7 +407,10 @@ namespace bitsery { void procEnableBitPacking(const Fnc& fnc, std::false_type) { //create serializer using bitpacking wrapper BPEnabledType tmp(_writer, _context); + // move internal context to and from of bitpacking enabled serializer + tmp._internalContext = std::move(_internalContext); fnc(tmp); + _internalContext = std::move(tmp._internalContext); } //these are dummy functions for extensions that have TValue = void @@ -423,6 +429,7 @@ namespace bitsery { }; + //helper type template using Serializer = BasicSerializer>; diff --git a/tests/serialization_context.cpp b/tests/serialization_context.cpp index 5acb0dd..db92913 100644 --- a/tests/serialization_context.cpp +++ b/tests/serialization_context.cpp @@ -130,4 +130,32 @@ TEST(SerializationContext, ContextIfExistsReturnsNullWhenTypeDoesntExists) { DeserializerConfigWithContext des{InputAdapter{buf.begin(), 1}, &extCtx2}; EXPECT_THAT(des.contextOrNull(), ::testing::NotNull()); EXPECT_THAT(des.contextOrNull(), ::testing::IsNull()); -} \ No newline at end of file +} + +TEST(SerializationContext, WhenBitPackingIsEnabledThenInternalContextIsMovedToNewInstanceAndMovedBackAfterwards) { + Buffer buf{}; + using Ser = SerializerConfigWithContext; + using BPSer = typename Ser::BPEnabledType; + + using Des = DeserializerConfigWithContext; + using BPDes = typename Des::BPEnabledType; + + Ser ser{buf, nullptr}; + *ser.context() = 1; + EXPECT_THAT(*ser.context(), Eq(1)); + ser.enableBitPacking([](BPSer& s) { + EXPECT_THAT(*s.context(), Eq(1)); + *s.context() = 2; + }); + EXPECT_THAT(*ser.context(), Eq(2)); + + Des des{InputAdapter{buf.begin(), 1}, nullptr}; + *des.context() = 3; + EXPECT_THAT(*des.context(), Eq(3)); + des.enableBitPacking([](BPDes& d) { + EXPECT_THAT(*d.context(), Eq(3)); + *d.context() = 4; + }); + EXPECT_THAT(*des.context(), Eq(4)); + +}