Defines struct type that is guaranteed to be stored in a contiguous byte buffer including all referenced arrays / pointers.
Home for binary contiguous Deserializer and utilities that use it. Check documentation of Deserializer for more details.
Enhancement to VersionDecorator that allows converting through multiple struct versions at once. It is kept separate from core implementation because additional overhead may be not suitable for real-time apps
Home for binary contiguous Serializer. Check the Serializer struct documentation for more details.
Collection of common utilities built on top of (de)serializer
Public imports
Public imports
Public imports
Public imports
Does series of tests on checked to verify that it is equal to struct returned by defaultS()
Returns the number of bytes used to serialise array, recursing into the elements of array if Element is a dynamic array type. No recursion is done if Element is a value type containing dynamic arrays.
Deserialise serializer_output in the trivial way to verify all dynamic array slices are null.
testArray!(op)(a, b) is equivalent to testArray!(op)(cast(const(void)[])a, cast(const(void)[])b), which allows for testArray!(op)(a, null) avoiding D2 trouble with typeof(null).
Format Explained
`contiguous.VersionDecorator` adds struct versioning information to the basic binary serialization format. It expects struct definitions with additional meta-information available at compile-time and prepends a version number byte before the actual data buffer. Upon loading the serialized data, the stored version number is compared against the expected one and automatic struct conversion is done if needed. It only allows conversion through one version increment/decrement at a time.
`contiguous.MultiVersionDecorator` is almost identical to plain `VersionDecorator` but allows the version increment range to be defined in the constructor. Distinct classes are used so that, if incoming data accidentally is too old, performance-critical applications will emit an error rather than wasting CPU cycles converting through multiple versions. For other aplications multi-version implementation should be more convenient.
API
The contiguous serialization format and the version decorator are primarily designed as a way to interchange D structs between different applications that may expect different versions of those struct layout. It is recommended to completely strip the version information with the help of the decorator upon initially reading a record, and to use the resulting raw contiguous buffer internally in the application (i.e. in a cache). That way you can use any of the serialization/deserialization utilities in the application without thinking about the version meta-data
Typical code pattern for a cache:
1. Define a `Cache` of `Contiguous!(S)` elements.
2. When receiving external data we do `version_decorator.loadCopy!(S)(dht_data, cache_element)`
3. Use `contiguous.Util.copy(cache_element, contiguous_instance)` for copying the struct instance if needed
4. Use `contiguous_instance.ptr` to work with deserialized data as if it was `S*`
It is likely that you will need to change the code to use strongly-typed `Contiguous!(S)` persistent buffer instead of raw `void[]` buffer. Possibly multiple such buffers if the old one was reused for different struct types. This may result in small memory footprint increase at the benefit of better type safety and optimized copy operations.
You can completely abandon the resulting the `Contiguous!(S)` instance and use/store the plain `S*` instead (retrieved via .ptr getter) which will work as long as underlying buffer persists. This is however slightly discouraged because if you will need to copy the data later, it will be impossible to use optimized version without unsafe explicit casts.