OPCFoundation / UA-Java-Legacy

This repository is provided by OPC Foundation as legacy support for an Java version for OPC UA.
https://github.com/OPCFoundation/UA-.NETStandard
Other
355 stars 227 forks source link

Remove EncoderCalc, refactor logic to use BinaryEncoder or skip size precalc where possible #168

Closed bjakke closed 5 years ago

bjakke commented 6 years ago

EncoderCalc and BinaryEncoder have almost the exact logic, with the difference that EncoderCalc only calculates the size and BinaryEncoder actually puts the bytes to something given in constructor.

There is a standard class ByteArrayOutputStream, which can be passed to BinaryEncoder to avoid knowing the exact size beforehand. It behaves like ArrayList, but for bytes. Additionally it is possible to make equivalent OutputStream that would only calculate the bytes. Therefore there is no reason to have a separate EncoderCalc class with duplicate logic. Even making one that would throw after a limit is reached to cover use-case that a Message would be too large to encode (which normally does not happen very often) is possible.

Therefore for 1.04 it is best to remove the EncoderCalc and e.g. IEncodeableSerializer.calcEncodeable and others like that. As a first step the existing code can be refactored to calc the size via ByteArrayOutputStream.size() and later the size calculation can be removed if it is a use-case where it is not needed.

This would also solve the extra times a Structure needs to be calculated/put to an Encoder (#134).

This avoids writing duplicate logic for multidim array encodings (#161).

bjakke commented 6 years ago

Note: There might be slight perf drop as ByteArrayOutputStream will need to copy the backing array if it grows over it's capasity (same as with ArrayList), if no size precalc is done. However it might still be even faster than the current logic for actually calculating the size beforehand (as this will multiply by factor of 2 in each nested Structure due to how it works). Anyway if it would be slower, it is possible to revert the old way by just making e.g. "ByteCalculatingOutputStream" that would only calc the size and pass that to BinaryEncoder, if needed.