17. Variable Length and Fixed Length
ByteClap clearly distinguishes between fixed-length data types and variable-length data types.
A fixed-length data type is a data type of a type that always has the same data size regardless of what value is set (for example, int type is 4 bytes, double type is 8 bytes).
A variable-length data type indicates a data type whose data size changes depending on the content to be set. For example, it is a data type such as List or string.
In ByteClap processing, basically fixed-length data types are often more advantageous in terms of speed.
For this reason, some variable-length types can be handled as fixed length by specifying the upper limit of size in advance.
(However, when fixed length handling is used, since the maximum data size is always secured at all limits, the data size is often larger than when variable length is handled)
Basically, the Converter / Processor is defined as a pair for fixed length and variable length, and the name of the fixed length Converter / Processor is the name obtained by adding "FL" at the end of the name of the variable length Converter / Processor .
Below is a list of interfaces of Converters / Processors defined in ByteClap.
List of interface of Converter
List of interface of Processor
When constructing a Converter / Processor with a builder, if the added field is only a fixed length field, the output Converter / Processor will be a fixed length interface.
In the sample below, all the fields create converters of fixed length class.
In L.8, it indicates that an instance of the converter is set in the variable of the fixed length interface.
The next sample specifies the upper limit of the size and treats the character string as fixed length.
L.11 specifies the upper limit of the size of the string.
As a result, all fields are handled as fixed lengths, and it is possible to receive converters on a fixed length interface.
Since all fixed-length interfaces inherit the variable-length interfaces of pairs, even if all the fields are fixed-length as in the above example, they can be received with a variable-length interface.
If you can not tell whether the result you built with the builder is fixed length, try adding FL after the converter name as a test. If the construction result is fixed length, it can be compiled as it is, but if it is variable length it will result in a compile error.
The Intermediate Byte Data Converter / Processor reduces the amount of work for serializing / deserializing the entire target object by having the target object have byte data and executing serialization / deserialization at the timing accessed to the field It is built by using IntermediateByteDataConverterBuilder.
The following is a sample construction of an Intermediate Byte Data Converter using IntermediateByteDataConverterBuilder.
16. Function and construction method of Intermediate Byte Data Converter / Processor
Intermediate Converter differ from the standard converters in the following points.
-
The target data type inherits IntermediateData
-
All fields to be processed are defined by IField <TValue>. * TValue is the type of value to be given to the field
-
The target object needs to be created by the Converter or Processor's CreateData method.
-
Create<TTarget>(Func<TTarget> createInstance, IntermediateFieldType defaultIntermediateFieldType, ByteOrderType byteOrderType, IntermediateByteDataConverterMode mode)
-
Create<TTarget>(Func<TTarget> createInstance, IntermediateFieldType defaultIntermediateFieldType, ByteOrderType byteOrderType)
-
Create<TTarget>(Func<TTarget> createInstance, IntermediateFieldType defaultIntermediateFieldType)
-
Create<TTarget>(IntermediateFieldType defaultIntermediateFieldType, ByteOrderType byteOrderType, IntermediateByteDataConverterMode mode)
-
Create<TTarget>(IntermediateFieldType defaultIntermediateFieldType, ByteOrderType byteOrderType)
-
Create<TTarget>(IntermediateFieldType defaultIntermediateFieldType)
The Create method has the following overload
◆ ビルダーの解説
Add<TField>(IntermediateFieldType intermediateFieldType, Action<TTarget, IField<TField>> setter, IProcessor<TField> processor)
Unlike other Converters, Intermediate Converters need to define member variables with IField <TValue> type.
The builder's Add method specifies the process of setting an Intermediate Field object for this member variable. (Therefore, we do not specify getter as argument of Add method)
The IntermediateFieldType specified in the Create method acts as a default value and applies to all fields added without specifying an IntermediateFieldType. To add a field with IntermediateFieldType specified, use the following Add method.
The Converter outputs with the following method.
Converters built with IntermediateByteDataConverterBuilder are output on the IVersioningIntermediateByteDataConverter <TTarget> interface.
It inherits the following interface.
◆ Explanation of the Converter
-
IDeserializer<TTarget>
-
IReusableDeserializer<TTarget>
-
IProcessor<TTarget>
-
IReusableValueProcessor<TTarget>
-
IClassProcessor<TTarget>
-
IIntermediateProcessor<TTarget>
Processors built with IntermediateByteDataConverterBuilder are output on the IIntermediateByteDataProcessor<TTarget> interface.
It inherits the following interface.
◆ Explanation of the Processor
IIntermediateByteDataProcessor<TTarget> has the following properties and methods.
・int GetByteSize(TTarget target)
Returns the size of the serialized object specified in the argument.
First argument: The object whose size you want to retrieve.
Returns: size
・void Serialize(byte[] bytes, ref int offset, TTarget target)
Perform serialization.
First argument: Data after serialization is set. You need to create and pass a byte array with the size required for serialization.
Second argument: Specify the storage start position of the serialized data. After execution, the serialization end position + 1 is stored.
Third argument: Specify the object to be serialized.
・int GetByteSize(byte[] bytes, int offset)
Returns the size of the target data of this Processor.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor.
Returns: size
・TTarget Deserialize(byte[] bytes, ref int offset)
Perform deserialization.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
・TTarget Deserialize(TTarget target, byte[] bytes, ref int offset)
Perform deserialization by reusing instance.
First argument: instance to reuse.
Second argument: a byte array containing serialized data.
Third argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
・IntermediateByteDataSubClessParameter<TTargetSub> CreateSubClassParameter<TTargetSub>()
Information on the processing target field set in this Processor is stored in SubClessParameter and returned.
When creating a Processor of a derived class of this Processor's target class, passing this information to the Builder's AddBaseClassParameter method will take over the information of the processing target field.
Generic type argument: type of derived class
Return value: Information on the target field owned by this Processor
Note: This function does not work properly in iOS environment. For details see "Note 1. iOS environment restrictions"
・TTarget CreateData()
Create a new instance of the target data type and initialize the field.
IVersioningIntermediateByteDataConverter <TTarget> has the following properties and methods.
・IVersioningIntermediateByteDataProcessor<TTarget> Processor
Returns the Processor responsible for the conversion process of this Converter
・IVersioningIntermediateByteDataConverter<TTarget> AddVersion(int versionNumber, IDeserializer<TTarget> deserializer)
Add another version of Deserializer to this Converter.
First argument: version number
Second argument: Deserializer to be added
Return value: Called object (method chain)
・byte[] Serialize(TTarget target)
Perform serialization.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・byte[] SerializeWithoutTrimming(TTarget target)
Perform serialization. However, it does not trim the result.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・TTarget Deserialize(byte[] bytes)
Perform deserialization.
First argument: A byte array containing serialized data.
Returns: The deserialized object.
・TTarget Deserialize(TTarget value, byte[] bytes)
Perform deserialization by reusing instance.
First argument: Instance to reuse.
Second argument: a byte array containing serialized data.
Returns: The deserialized object.
・TTarget CreateData()
Create a new instance of the target data type and initialize the field.
IIntermediateByteDataProcessor<TTarget> ToProcessor()
The Processor outputs with the following method.
This method outputs Versioning Converter. It is possible to specify a version number as an argument, and if you omit the argument, the version number is 0.
IVersioningIntermediateByteDataConverter<TTarget> ToConverter(int versionNumber)
-
IConverter<TTarget>
-
IClassConverter<TTarget>
-
IVersioningConverter<TTarget>
-
IVersioningClassConverter<TTarget>
-
IIntermediateConverter<TTarget>
-
IIntermediateByteDataConverter<TTarget>
The serialization / deserialization behavior for each field changes depending on the value specified for IntermediateFieldType.
Valid values are as follows.
The Add method has the following format. (For the actual method names for each type, refer to "List of Standard Supported Data Types")
AddTypeName(Action<TTarget, IField<TField>> setter)
Welcome to the world of ByteClap!
ByteClap is a static serializer building library for C # that is available on Unity ™.
By simply writing a simple program, you can incorporate ultra high-speed, high-performance serialization processing in your game.
Let's see how to use ByteClap!
Please purchase ByteClap from Unity Asset Store and download it.
Unity Asset Store: https://www.assetstore.unity3d.com/en/#!/content/93858
Once downloading is completed, you can start using it immediately!
1. Installing ByteClap
2. Basics
ByteClap is a library for easily building static serializer.
"Static serializer" means to realize serialization processing without using dynamic code analysis / generation technology such as reflection and expression trees. Therefore, although it takes time to code necessary information for serialization, it is possible to realize much faster processing than dynamic serialization technology.
Also, detailed customization and tuning can be easily described in the program.
Well, please see the sample code below
This is a simple example that you can see a series of serialization / deserialization processing using ByteClap.
When you create the appropriate game object in Unity's Hierarchy window, attach this script and press the execute button, "num = 123, str = abc" will be displayed on the console (name of script is "Sample01.cs" Please).
I will briefly explain the sample.
L.2: The using directive specifies the Omanju.ByteClap namespace.The basic functions of ByteClap are contained in this namespace.
L.4 - 12: Class to be serialized. It has an int type field "num" and a string type field "str" and has a Converter in static.
L.8 - 11: Use the Builder to define the Converter of SampleClass.
L.16 - 23: Initialize SampleClass, serialize and deserialize it using the converter, and output the result as a debug log.
In this way, ByteClap uses a class called a Builder to define a Converter and serialize and deserialize it using a Converter.
Using a builder makes it very easy to define Converters so that despite the form of a static serializer, coding costs can be kept low.
3. Converter and Processor
In the previous section I explained that serialization / deserialization is performed using a Converter. The Converter has an object called a Processor inside, and the serialization / deserialization processing entity is defined in this Processor.
The Converter has only a wrapper-like role to hide burdensome preprocessing etc. necessary for using the Processor and make it easy to use.
Processor is the most important and fundamental function in ByteClap. One Processor processes one data type. For all data types that can be serialized / deserialized by ByteClap, corresponding Processors are defined.
In the example in the previous section, the builder used to create a converter, but you can also create a processor with a builder.
Processors are used in various situations, such as being used in building processes using builders, becoming arguments when using other converters and processors, and so on.
The namespace defined in the ByteClap library below defines the function created for the purpose to be used by the user.
4. Namespace
In addition to the namespaces introduced in the table above, there are several namespaces ending with ".Core".
This is the namespace in which the functions created by the ByteClap library are defined for internal use.
Bug fixes and minor updates may increase or decrease functions without notice, or the interface may be changed. Therefore, it is not recommended to use directly (and We do not provide explanatory materials at the moment).
If you use it directly, please be careful.
◆ About "Core" namespace
Of these, Omanju.ByteClap.Logs and Omanju.ByteClap.Selectors do not have much opportunity to use at first.
Basically, if you specify Omanju.ByteClap for the using directive and if you are dealing with the processor directly, you will also use Omanju.ByteClap.Processors as well.
To use serialization / deserialization using ByteClap, you will use a builder to define Converters and Processors, there are several classifications with different uses.
Here is the list.
5. Classification of Processors, Converters and Builders
In ByteClap, some types of data types such as primitive types and commonly used collection types are predefined as processors so that they can be easily used.
Even within converters / processors built using builders, these processors are used for the conversion processing of each field.
For processors defined by the standard, refer to "List of Standard Supported Data Types".
6. Standard supported Processors
7. Filter type processor
Some of the processors defined by ByteClap work to add functions to the set processor by setting other processors.
Here is the list.
In addition to these, some builders have specific parameters.
For details, refer to the explanation by builder and the API document.
② Add fields
In the Builder's Create() method, declare the start of construction.
The Create() method has an overload that allows you to specify several arguments, you can customize the Converter / Processor you build with the value you specify in the argument.
Values that can be specified as arguments to the Create() method depend on the type of builder, but typical ones are as follows.
public static readonly IConverter<SampleClass> converter = ClassConverterBuilder.Create<SampleClass>()
.AddInt(o => o.num, (o,v) => o.num = v)
.AddString(o => o.str, (o,v) => o.str = v)
.ToConverter();
Building a converter / processor using a builder is done in the following three steps.
① Declaration of start of construction
② Add fields
③ Output of converter / processor
Below, we will explain the details based on the converter definition of Sample01.cs.
① Declaration of start of construction
8. Builder basics
public static readonly IConverter<SampleClass> converter = ClassConverterBuilder.Create<SampleClass>()
.AddInt(o => o.num, (o,v) => o.num = v)
.AddString(o => o.str, (o,v) => o.str = v)
.ToConverter();
AddTypeName(Func<TTarget, TField> getter, Action<TTarget, TField> setter)
This is the part to add the field to be serialized.
Since each method of the builder adopts a method chain pattern, it is possible to describe multiple method calls concatenated with ".".
The fields to be added must be specified one by one with the Add method.
The Add method is roughly expressed in the following format.
public static readonly IConverter<SampleClass> converter = ClassConverterBuilder.Create<SampleClass>()
.AddInt(o => o.num, (o,v) => o.num = v)
.AddString(o => o.str, (o,v) => o.str = v)
.ToConverter();
Setter, getter, and the processor for the target field is specified.
Some fields have multiple overloads that specify optional arguments.
Please refer to the API document for details.
③ Output of Converter / Processor
Add(Func<TTarget, TField> getter, Action<TTarget, TField> setter, IProcessor<TField> processor)
For the combination of field type and method name, Please refer to "List of Standard Supported Data Types".
To add a field of a type that does not have a dedicated method, use the generic Add method.
Finally we output Converter or Processor.
Use ToConverter() method for Converter output and ToProcessor() method for Processor output.
◆ Output of the Converter
Calling the ToConverter() method will output the Converter with the contents built by the builder.
This Converter is a derivative version of Versioning Converter that handles versioned byte data.
It roughly has the following structure.
Versioning Converter
Versioning Processor
Latest Version Processor
Processor for Field1
Processor for Field2
・
・
・
Deserializer for
past version
(Nothing is set at the output time of the converter)
-
The Versioning Converter has a Versioning Processor inside, and most processing is delegated to the Versioning Processor.
-
The Versioning Processor internally has the latest version Processor and the plural past version Deserializers, the serialization processing and the deserialization of the latest version of byte data are performed by the latest version Processor, the deserialization of the past version byte data is for the past version the Deserializer is in charge.(However, at the time of Versioning Converter generation, no deserializer of the past version is set. Please refer to "9. Versioning Converter / Processor" for details.)
-
The latest Processor has a Processor for the field for each field of the target object, and the conversion process of each field of the target object is executed by this field Processor.
The "Latest Processor" in this is the same as the Processor output by ToProcessor().
In addition, ToConverter() accepts the version number as an optional argument of int type. This is set as the version number of the latest processor. It is 0 if omitted.
◆ Output of the Processor
Calling the ToProcessor() method will output the Processor with the contents built by the Builder.This Processor is a non-versioned basic Processor.
Some Builders have output methods other than ToConverter() and ToProcessor(), and others require builder specific arguments. For details, refer to the explanation by Builder and the API document.
The solution when a change is made to the field of the data type to be serialized is to use the Versioning Converter. This allows you to convert the byte data outputted in the layout before the modification into the object with the latest layout and read it.
The following is a sample program using Versioning Converter.
9. Versioning Converter / Processor
AddVersion(int versionNumber, IDeserializer<TTarget> deserializer)
The Versioning Converter has a Versioning Processor inside. The Versioning Processor consists of one Processor that handles the latest version layout and multiple Deserializers that deal with past layouts. These Processor / Deserializers are identified by the unique version number specified when adding to the Versioning Processor, and the Processor / Deserializers to be called during deserialization is determined based on the version number written in the byte data. When serializing, the latest version Processor will always work.
I will briefly explain the whole sample.
L.5 - 11: This defines the class of the first version (First Version) and its Converter.
This Converter is outputting without specifying the version number. Therefore, version number "0" is assigned to byte data serialized by this Converter.
L.13 - 30: This defines the new version's class (SecondVersion) and its Converter.
In L.20, the Converter is output with the version number "1" specified.
In L. 21 - 28, the past version of Deserializer is set for this Converter.
L.32 - 48: It is operation confirmation using data of each old and new version.
Both the old version byte data created in L.36 and the new version byte data created in L.41 are deserialized using the new version of the Converter in L.43 - 44.
I will explain the setting of the past version Deserializer of L.21 - 28 in more detail.
Calling in L.21 is the AddVersion method of Versioning Converter (note: that it is not a builder method). This method takes the following form
This specifies the version number and Deserializer for it.
Since the Processor (IProcessor <TTarget>) inherits the Deserializer (IDeserializer <TTarget>), you can also use the Processor to add the version.
However, in this example, we use TemporaryDataDeserializer <TTarget, TWork> to use the processor of FirstVersion converter. This is converting the FirstVersion type object deserialized by the processor of the FirstVersion converter into the object of the SecondVersion type.
◆ TemporaryDataDeserializer<TTarget, TWork>
It Deserializes into an object of TWork once, converts it to object of TTarget, and outputs it.
The constructor is defined as follows.
A Deserializer for deserializing to TWork with the first argument is specified.Conversion processing from TWork to TTarget is specified with the second argument.
In L22., In order to pass it to the constructor of TemporaryDataDeserializer<TTarget, TWork>, we get a processor from FirstVersion converter.
The figure below shows the structure of the Versioning Converter listed in "8. Builder basics" and added the state of FirstVersion Converter.
TemporaryDataDeserializer(IDeserializer<TWork> deserializer, Func<TWork, TTarget> convertFunc)
Versioning Converter
(FirstVersion.converter)
Versioning Processor
(FirstVersion.converter.Processor)
Latest Version Processor
[version number: 0]
(FirstVersion.converter.Processor.LatestVersion)
IntProcessor(for "num")
Deserializer for past version
(Nothing is set)
FirstVersion.converter is the outermost "Versioning Converter".
In FirstVersion.converter.Processor, the middle "Versioning Processor" is returned. (The Processor property of the converter returns the processor that the converter has)
In FirstVersion.converter.Processor.LatestVersion, "Latest Version Processor" is returned.
The SecondVersion.converter that added this has the following structure.
As described above, by adding a deserializer capable of processing older version byte data to the Versioning Converter, one Converter can deal with multiple version deserialization processing.
Versioning Converter
(SecondVersion.converter)
Versioning Processor
(SecondVersion.converter.Processor)
Latest Version Processor
[version number: 1]
(SecondVersion.converter.Processor.LatestVersion)
IntProcessor(for "num")
StringProcessor(for "str")
Deserializer for past version
[version number: 0]
TemporaryDataDeserializer<SecondVersion, FirstVersion>
Processor acquired from FirstVersion.converter.Processor.LatestVersion
IntProcessor(for "num")
The solution when the data type to be serialized has polymorphism is to use a Polymorphic Processor. This allows you to restore the serialized instance type during deserialization.
The following is a sample of processing using a Polymorphic Processor.
10. Polymorphic Processor
A Polymorphic Processor consists of multiple Processors targeting data types with the same base type. Each Processor is identified by a unique ID that is specified when adding to the Polymorphic Converter and assignment is done during the conversion process.
I will briefly explain the whole sample.
L.5 - 25: Definition of base class, definition of Processor of base class, definition of Converter with Polymorphic Processor.
L.20: This is creating a Converter with a Polymorphic Processor created in L.21 - 23.
L.21: Creating instances of Polymorphic Processors. The ByteOrderType of the argument is a byte order specification for ID.
L.22: Processor of BaseClass is being added with ID = 0.
L.23: Processor of SubClass is being added with ID = 1.
L.27 - 42: Derived class definitions and derived class Processor definitions.
L.44 - 57: It is an operation confirmation using an instance of the base class and an instance of the derived class.
As described above, if derivation type Processors (and the base type Processor) are set in the Polymorphic Processor for the base type, it is possible to automatically identify the type to be converted, Perform a serialization / deserialization using a Processor for the type.
The Intermediate Converter is a technology aimed at speeding up the serialization / deserialization and dispersing the processing load.
The object to be processed by this Converter has data called Intermediate Byte Data. The Intermediate Byte Data is a memory area prepared for each field of the target object and holds the field value as byte data, and serialization / deserialization is executed at the timing when the field is accessed. This aims to improve the processing speed by reducing the work of serializing / deserializing the entire object.
The following figure is a rough representation of the operation during deserialization of a normal Converter and an Intermediate Converter.
11. Intermediate Converter
Field Value A
Field Value B
Field Value C
③ If the field value is requested, output as it is
② Return the deserialized object
① Deserialize all fields at once and set them in each field of the target object
Byte Data
Field Value A
Deserialization of normal Converter
Target Object
Converter
Field Value A
Field Value B
Field Value C
Deserialization of Intermediate Converter
Byte Data
Intermediate Byte Data A
Intermediate Byte Data B
Intermediate Byte Data C
Intermediate Byte Data A
Intermediate Byte Data B
Intermediate Byte Data C
Converter
Target Object
Field Value A
① Byte data is divided for each field and stored as Intermediate Byte Data
② Return an object with Intermediate Byte Data
③ Deserialize and return only the requested field value
In this way, all the fields are converted at once in a normal Converter, whereas the Intermediate Converter divides the conversion process into the timing when the field is accessed.
(Serialization processing is roughly the reverse flow)
In order to realize such processing, the data type to be converted by the Intermediate Converter must be defined as follows.
-
The target data type must inherit IntermediateData
-
Field of target data type must be defined with IField<TValue> type
-
An instance of the target data type needs to be generated using an Intermediate Converter
Since it is such a structure, the description method when constructing the Intermediate Converter with the builder differs slightly from the normal Converter.
Please see the sample below.
This sample rewrote the processing of Sample01 using an Intermediate Converter.
The difference from Sample01 is as follows.
L.4: The target class inherits IntermediateData
L.5 - 6: The fields of the target class are IField <TValue>
L. 10 - 11: Argument of Add method is different
The normal Converters specified process of get and set field values. The Intermediate Converter specifies process of set the Intermediate Field object for the variable of type IField <TValue>.
L.17: Creating an instance of the target class with an Intermediate Converter
L.18 - 19, 24: Setting and getting values to fields are done through the Value property of IField<TValue>.
As mentioned above, there are many rules on use compared to normal converters, but in some cases it can be speeded up considerably by using properly.
12. Function and construction method of Class Converter / Processor
The Class Converter / Processor is a function for serializing / deserializing compound data types of class type (reference type), and it is constructed with ClassConverterBuilder.
The following is a sample of building a Class Converter using ClassConverterBuilder.
AddTypeName(Func<TTarget, TField> getter, Action<TTarget, TField> setter)
-
Create<TTarget>(Func<TTarget> createInstance, ByteOrderType byteOrderType, ClassConverterMode mode)
-
Create<TTarget>(Func<TTarget> createInstance, ByteOrderType byteOrderType)
-
Create<TTarget>(Func<TTarget> createInstance)
-
Create<TTarget>(ByteOrderType byteOrderType, ClassConverterMode mode)
-
Create<TTarget>(ByteOrderType byteOrderType)
-
Create<TTarget>()
The Add method has the following format. (For the actual method names for each type, refer to "List of Standard Supported Data Types")
◆ Explanation of the Builder
The Create method has the following overload
IClassSymmetricProcessor<TTarget> ToProcessor()
The Processor outputs with the following method.
This method outputs a derived type of Versioning Converter. It is possible to specify a version number as an argument, and if you omit the argument, the version number will be 0.
IVersioningClassSymmetricConverter<TTarget> ToConverter(int versionNumber)
The Converter outputs with the following method.
-
IConverter<TTarget>
-
IClassConverter<TTarget>
-
IVersioningConverter<TTarget>
-
IVersioningClassConverter<TTarget>
-
IClassSymmetricConverter<TTarget>
Converters built with ClassConverterBuilder are output on the IVersioningClassSymmetricConverter <TTarget> interface.
It inherits the following interface.
◆ Explanation of the Converter
IVersioningClassSymmetricConverter <TTarget> has the following properties and methods.
・IVersioningClassSymmetricProcessor<TTarget> Processor
Returns the Processor responsible for the conversion process of this Converter
・IVersioningClassSymmetricConverter<TTarget> AddVersion(int versionNumber, IDeserializer<TTarget> deserializer)
Add another version of Deserializer to this Converter.
First argument: version number
Second argument: Deserializer to be added
Return value: Called object (method chain)
・byte[] Serialize(TTarget target)
Perform serialization.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・byte[] SerializeWithoutTrimming(TTarget target)
Perform serialization. However, it does not trim the result.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・TTarget Deserialize(byte[] bytes)
Perform deserialization.
First argument: A byte array containing serialized data.
Returns: The deserialized object.
・TTarget Deserialize(TTarget value, byte[] bytes)
Perform deserialization by reusing instance.
First argument: Object to reuse.
Second argument: a byte array containing serialized data.
Returns: The deserialized object.
* About trim
Some Processors provided by ByteClap allocate sizes larger than the size necessary for serialization when preparing a byte array in preparation for serialization.
This method is adopted when the execution time can be shortened by roughly allocating the necessary and sufficient size in the data type which takes time to calculate the accurate size.
If such a data type is included in the fields of the object to be converted, unused parts may be included in the serialized byte array, but in normal serialization, only the part being used is copied It creates and returns a new byte array.
Using SerializeWithoutTrimming will return the byte array containing the unused portion as it is, so the size of the byte array is wasted, but you can save the cost of re-creating the byte array.
* About reusing instances
The normal deserialization process creates a new instance of the data type to be output and sets the deserialized value. Instance Reuse Deserialization sets the deserialized value to the instance received in the argument.
For example, use this function in the following situations
-
Use to shorten execution time when converting a data type that takes time to generate an instance
-
Use when you need to continue to use a specific instance
etc...
Instance reuse is available only when the target data type is class (reference type). It can not be used when the structure (value type) is the target data type.
-
IClassProcessor<TTarget>
-
IReusableValueProcessor<TTarget>
-
IProcessor<TTarget>
-
IReusableDeserializer<TTarget>
-
IDeserializer<TTarget>
Processors built with ClassConverterBuilder are output on the IClassSymmetricProcessor<TTarget> interface.
It inherits the following interface.
◆ Explanation of the Processor
IClassSymmetricProcessor<TTarget> has the following properties and methods.
・int GetByteSize(TTarget target)
Returns the size of the serialized object specified in the argument.
First argument: The object whose size you want to retrieve.
Returns: size
・void Serialize(byte[] bytes, ref int offset, TTarget target)
Perform serialization.
First argument: Data after serialization is set. You need to create and pass a byte array with the size required for serialization.
Second argument: Specify the storage start position of the serialized data. After execution, the serialization end position + 1 is stored.
Third argument: Specify the object to be serialized.
・int GetByteSize(byte[] bytes, int offset)
Returns the size of the target data of this Processor.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor.
Returns: size
・TTarget Deserialize(byte[] bytes, ref int offset)
Perform deserialization.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
・TTarget Deserialize(TTarget target, byte[] bytes, ref int offset)
Perform deserialization by reusing instance.
First argument: instance to reuse.
Second argument: a byte array containing serialized data.
Third argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
・SubClessParameter<TTargetSub> CreateSubClassParameter<TTargetSub>()
Information on the processing target field set in this Processor is stored in SubClessParameter and returned.
When creating a Processor of a derived class of this Processor's target class, passing this information to the Builder's AddBaseClassParameter method will take over the information of the processing target field.
Generic type argument: type of derived class
Return value: Information on the target field owned by this Processor
Note: This function may not work properly in iOS environment. For details see "Note1. iOS environment restrictions".
* Inheritance of field information using CreateSubClassParameter
The following is a sample that inherits field information.
In L.21 we are passing the return value of the CreateSubClassParameter method of the InheritSampleBase Processor to the builder's AddBaseClassParameter method.
If you set this script to the appropriate game object on the Unity editor and press the execute button, "num = 123, str = abc, num2 = 456" is displayed on the console.
This indicates that the field information has been inherited from the InheritSampleBase Processor to the InheritSampleSub Converter.
The Struct Converter / Processor is a function for serializing / deserializing compound data types of struct type (value type), and it is constructed with StructConverterBuilder.
The following is a sample of building a Struct Converter using StructConverterBuilder.
13. Function and construction method of Struct Converter / Processor
IVersioningConverter<TTarget> ToConverter(int versionNumber)
This method outputs Versioning Converter. It is possible to specify a version number as an argument, and if you omit the argument, the version number is 0.
The Processor outputs with the following method.
IProcessor<TTarget> ToProcessor()
The Add method has the following format. (For the actual method names for each type, refer to "List of Standard Supported Data Types")
-
Create<TTarget>(Func<TTarget> createInstance, ByteOrderType byteOrderType, StructConverterMode mode)
-
Create<TTarget>(Func<TTarget> createInstance, ByteOrderType byteOrderType)
-
Create<TTarget>(Func<TTarget> createInstance)
-
Create<TTarget>(ByteOrderType byteOrderType, StructConverterMode mode)
-
Create<TTarget>(ByteOrderType byteOrderType)
-
Create<TTarget>()
AddTypeName(StructFieldGetter<TTarget, TField> getter, StructFieldSetter<TTarget, TField> setter)
The Converter outputs with the following method.
The Create method has the following overload.
◆ Explanation of the Builder
IProcessor<TTarget> has the following properties and methods.
・int GetByteSize(TTarget target)
Returns the size of the serialized object specified in the argument.
First argument: The object whose size you want to retrieve.
Returns: size
・void Serialize(byte[] bytes, ref int offset, TTarget target)
Perform serialization.
First argument: Data after serialization is set. You need to create and pass a byte array with the size required for serialization.
Second argument: Specify the storage start position of the serialized data. After execution, the serialization end position + 1 is stored.
Third argument: Specify the object to be serialized.
・int GetByteSize(byte[] bytes, int offset)
Returns the size of the target data of this Processor.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor.
Returns: size
・TTarget Deserialize(byte[] bytes, ref int offset)
Perform deserialization.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
-
IDeserializer<TTarget>
Processors built with StructConverterBuilder are output on the IProcessor<TTarget> interface.
It inherits the following interface.
◆ Explanation of the Processor
IVersioningConverter<TTarget> has the following properties and methods.
・IVersioningProcessor<TTarget> Processor
Returns the Processor responsible for the conversion process of this Converter
・IVersioningConverter<TTarget> AddVersion(int versionNumber, IDeserializer<TTarget> deserializer)
Add another version of Deserializer to this Converter.
First argument: version number
Second argument: Deserializer to be added
Return value: Called object (method chain)
・byte[] Serialize(TTarget target)
Perform serialization.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・byte[] SerializeWithoutTrimming(TTarget target)
Perform serialization. However, it does not trim the result.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・TTarget Deserialize(byte[] bytes)
Perform deserialization.
First argument: A byte array containing serialized data.
Returns: The deserialized object.
◆ Explanation of the Converter
Converters built with StructConverterBuilder are output on the IVersioningConverter<TTarget> interface.
It inherits the following interface.
-
IConverter<TTarget>
The Class Asymmetric Converter / Processor is a function for serializing / deserializing compound data types of class type (reference type), and it is constructed with ClassAsymmetricConverterBuilder.
When deserializing an Asymmetric Converter, the deserialization result is first set in the work object, and then the desired object is created from the work object.
Therefore, when there is a value that can be set only in the constructor, when there is a readonly specified value, when you want to set a value obtained by complicated calculation, etc., you can use it without changing the design of the target object .
Serialization of an Asymmetric Converter is the same processing as a normal Converter.
The following is a sample of building a Class Asymmetric Converter using ClassAsymmetricConverterBuilder.
14. Function and construction method of Class Asymmetric Converter / Processor
IVersioningClassAsymmetricConverter<TTarget, TWork> has the following properties and methods.
・IVersioningClassAsymmetricProcessor<TTarget, TWork> Processor
Returns the Processor responsible for the conversion process of this Converter
・IVersioningClassAsymmetricConverter<TTarget, TWork> AddVersion(int versionNumber, IDeserializer<TTarget> deserializer)
Add another version of Deserializer to this Converter.
First argument: version number
Second argument: Deserializer to be added
Return value: Called object (method chain)
・byte[] Serialize(TTarget target)
Perform serialization.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・byte[] SerializeWithoutTrimming(TTarget target)
Perform serialization. However, it does not trim the result.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・TTarget Deserialize(byte[] bytes)
Perform deserialization.
First argument: A byte array containing serialized data.
Returns: The deserialized object.
・TTarget Deserialize(TTarget value, byte[] bytes)
Perform deserialization by reusing instance.
First argument: Object to reuse.
Second argument: a byte array containing serialized data.
Returns: The deserialized object.
◆ Explanation of the Converter
Converters built with ClassAsymmetricConverterBuilder are output on the IVersioningClassAsymmetricConverter<TTarget, TWork> interface.
It inherits the following interface.
-
IConverter<TTarget>
-
IClassConverter<TTarget>
-
IVersioningConverter<TTarget>
-
IVersioningClassConverter<TTarget>
-
IClassAsymmetricConverter<TTarget, TWork>
IClassAsymmetricProcessor<TTarget, TWork> has the following properties and methods.
・int GetByteSize(TTarget target)
Returns the size of the serialized object specified in the argument.
First argument: The object whose size you want to retrieve.
Returns: size
・void Serialize(byte[] bytes, ref int offset, TTarget target)
Perform serialization.
First argument: Data after serialization is set. You need to create and pass a byte array with the size required for serialization.
Second argument: Specify the storage start position of the serialized data. After execution, the serialization end position + 1 is stored.
Third argument: Specify the object to be serialized.
・int GetByteSize(byte[] bytes, int offset)
Returns the size of the target data of this Processor.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor.
Returns: size
・TTarget Deserialize(byte[] bytes, ref int offset)
Perform deserialization.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
・TTarget Deserialize(TTarget target, byte[] bytes, ref int offset)
Perform deserialization by reusing instance.
First argument: instance to reuse.
Second argument: a byte array containing serialized data.
Third argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
・SubClessAsymmetricParameter<TTargetSub, TWorkSub> CreateSubClassParameter<TTargetSub, TWorkSub>()
Information on the processing target field set in this Processor is stored in SubClessParameter and returned.
When creating a Processor of a derived class of this Processor's target class, passing this information to the Builder's AddBaseClassParameter method will take over the information of the processing target field.
TTargetSub: Derived class type of the target class
TWorkSub: Derived class type of work object's class
Return value: Information on the target field owned by this Processor
Note: This function may not work properly in iOS environment. For details see "Note 1. iOS environment restrictions"
-
IClassProcessor<TTarget>
-
IReusableValueProcessor<TTarget>
-
IProcessor<TTarget>
-
IReusableDeserializer<TTarget>
-
IDeserializer<TTarget>
Processors built with ClassAsymmetricConverterBuilder are output on the IClassAsymmetricProcessor<TTarget, TWork> interface.
It inherits the following interface.
◆ Explanation of the Processor
IClassAsymmetricProcessor<TTarget, TWork> ToProcessor(Func<TTarget, TWork, TTarget> createInstance)
In the argument delegate, specify the processing to create the desired object from the reusable object and the work object.
The delegate is used both for normal deserialization and deserialization for reusing instances.
If called from deserialization without reusing the instance, the reusable object is set to null.
In the argument delegate, specify the process to create the desired object from the work object.
The delegate is used both for normal deserialization and deserialization for reusing instances.
The Processor outputted by this method does not use reuse instance even if deserialization that reuses the instance is executed.
IVersioningClassAsymmetricConverter<TTarget, TWork> ToConverter(Func<TTarget, TWork, TTarget> createInstance, int versionNumber)
First argument: Specify the process to create the desired object from the reuse instance and work object.
Second argument: It is possible to specify the version number. If the argument is omitted, the version number is 0.
The delegate specified for this first argument is used both for normal deserialization and deserialization for reusing instances.
If called from deserialization without reusing the instance, the reusable object is set to null.
IClassAsymmetricProcessor<TTarget, TWork> ToProcessor(Func<TWork, TTarget> createInstance)
The Processor outputs in one of the following methods.
First argument: Specify the process of creating the desired object from the work object.
Second argument: It is possible to specify the version number. If the argument is omitted, the version number is 0.
The delegate specified for this first argument is used both for normal deserialization and deserialization for reusing instances.
The Converter outputted by this method does not use reuse instance even if deserialization that reuses the instance is executed.
IVersioningClassAsymmetricConverter<TTarget, TWork> ToConverter(Func<TWork, TTarget> createInstance, int versionNumber)
The Converter outputs in one of the following methods.
AddTypeName(Func<TTarget, TField> getter, Action<TWork, TField> setter)
The Add method has the following format. (For the actual method names for each type, refer to "List of Standard Supported Data Types")
-
Create<TTarget, TWork>(ByteOrderType byteOrderType, ClassAsymmetricConverterMode mode)
-
Create<TTarget, TWork>(ByteOrderType byteOrderType)
-
Create<TTarget, TWork>()
The Create method has the following overload.
◆ Explanation of the Builder
15. Function and construction method of Struct Asymmetric Converter / Processor
The Struct Asymmetric Converter / Processor is a function for serializing / deserializing compound data types of struct type (value type), and it is constructed with StructAsymmetricConverterBuilder.
When deserializing an Asymmetric Converter, the deserialization result is first set in the work object, and then the desired object is created from the work object.
Therefore, when there is a value that can be set only in the constructor, when there is a readonly specified value, when you want to set a value obtained by complicated calculation, etc., you can use it without changing the design of the target object .
Serialization of an Asymmetric Converter is the same processing as a normal Converter.
The following is a sample of building a Struct Asymmetric Converter using StructAsymmetricConverterBuilder.
In the argument delegate, specify the process to create the desired object from the work object.
IProcessor<TTarget> ToProcessor(Func<TWork, TTarget> createInstance)
The Processor outputs with the following method.
First argument: Specify the process of creating the desired object from the work object.
Second argument: It is possible to specify the version number. If the argument is omitted, the version number is 0.
IVersioningConverter<TTarget> ToConverter(Func<TWork, TTarget> createInstance, int versionNumber)
The Converter outputs with the following method.
AddTypeName(Func<TTarget, TField> getter, Action<TWork, TField> setter)
The Add method has the following format. (For the actual method names for each type, refer to "List of Standard Supported Data Types")
-
Create<TTarget, TWork>(ByteOrderType byteOrderType, StructAsymmetricConverterMode mode)
-
Create<TTarget, TWork>(ByteOrderType byteOrderType)
-
Create<TTarget, TWork>()
The Create method has the following overload
◆ Explanation of the Builder
IVersioningConverter <TTarget> has the following properties and methods.
・IVersioningProcessor<TTarget> Processor
Returns the Processor responsible for the conversion process of this Converter
・IVersioningConverter<TTarget> AddVersion(int versionNumber, IDeserializer<TTarget> deserializer)
Add another version of Deserializer to this Converter.
First argument: version number
Second argument: Deserializer to be added
Return value: Called object (method chain)
・byte[] Serialize(TTarget target)
Perform serialization.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・byte[] SerializeWithoutTrimming(TTarget target)
Perform serialization. However, it does not trim the result.
First argument: Object to be serialized.
Return value: a byte array of the serialization result.
・TTarget Deserialize(byte[] bytes)
Perform deserialization.
First argument: A byte array containing serialized data.
Returns: The deserialized object.
-
IConverter<TTarget>
Converters built with StructAsymmetricConverterBuilder are output on the IVersioningConverter<TTarget> interface.
It inherits the following interface.
◆ Explanation of the Converter
-
IDeserializer<TTarget>
Processors built with StructAsymmetricConverterBuilder are output on the IProcessor<TTarget> interface.
It inherits the following interface.
◆ Explanation of the Processor
IProcessor<TTarget> has the following properties and methods.
・int GetByteSize(TTarget target)
Returns the size of the serialized object specified in the argument.
First argument: The object whose size you want to retrieve.
Returns: size
・void Serialize(byte[] bytes, ref int offset, TTarget target)
Perform serialization.
First argument: Data after serialization is set. You need to create and pass a byte array with the size required for serialization.
Second argument: Specify the storage start position of the serialized data. After execution, the serialization end position + 1 is stored.
Third argument: Specify the object to be serialized.
・int GetByteSize(byte[] bytes, int offset)
Returns the size of the target data of this Processor.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor.
Returns: size
・TTarget Deserialize(byte[] bytes, ref int offset)
Perform deserialization.
First argument: A byte array containing serialized data.
Second argument: The starting position of the target data of this Processor. After execution, the deserialization end position + 1 is stored.
Returns: The deserialized object.
Note 1. iOS environment restrictions
In the current situation, the simplest way to avoid these functions and obtain similar results is to set the scope of the base class field to protected or public, and when constructing a derived class processor, set the field of the base class to It is to add all fields including.
Measures and fixes of the ByteClap library are currently under consideration.
Sorry to trouble you, but please avoid the error by the above method until the measure is completed.