2. Type Mappings
This document explains how different types are mapped in each language.
Java
In Java types are mapped as:
| Type Name | Java-class |
|---|---|
| 32-bit integer | java.lang.Integer, int |
| 64-bit integer | java.lang.Long, long |
| 32-bit float | java.lang.Float, float |
| 64-bit float | java.lang.Double, double |
| String | java.lang.String |
| Boolean | java.lang.Boolean |
| Big Integer | java.math.BigInteger |
| Big Decimal | java.math.BigDecimal |
| Zoned Date Time | java.time.ZonedDateTime |
| UTC Date Time | java.time.Instant |
| Local Date Time | java.time.LocalDateTime |
| Local Date | java.time.LocalDate |
| Local Time | java.time.LocalTime |
| Byte Array | java.lang.byte[] |
| Array | java.util.List / java.util.ArrayList |
| Set | java.util.Set / java.util.HashSet |
| Map | java.util.Map / java.util.HashMap |
JavaScript
Because JavaScript is more restricted in its type system, some quirks and workarounds are needed to make everything work.
Basic Types
Most basic types are mapped as follows:
| Type Name | Actual Type |
|---|---|
| 32-bit integer | number |
| 64-bit integer | number |
| 32-bit float | number |
| 64-bit float | number |
| String | string |
| Boolean | boolean |
| Big Integer | bigint |
| Big Decimal | Custom Encoder needed |
| Zoned Date Time | Temporal.ZonedDateTime |
| UTC Date Time | Temporal.Instant |
| Local Date Time | Temporal.PlainDateTime |
| Local Date | Temporal.PlainDate |
| Local Time | Temporal.PlainTime |
| Byte Array | Uint8Array |
| Array | array |
| Set | Set |
| Map | Map |
Number Type Notes
Because JavaScript supports natively only 64-bit floats, other number types require conversions at runtime, which causes some special cases. For this, an underflow and overflow strategies are needed. The possibilities are:
Throwing an error (the default)
In this strategy an error is simply thrown during serialization or deserialization.
Number Capping
In this strategy, overflowing and underflowing numbers are capped to their minimum and maximum safe variations. For instance, for 64-bit integers, the maximum safe size is actually 56-bits.
This strategy can be configured as:
const cbot = Cbot.getInstance({
numberOverflowStrategy: {
onDeserialize: OnDeserializeOverflow.CAP_TO_BOUNDS,
onSerialize: OnSerializeOverflow.CAP_TO_BOUNDS
}
});
Not A Number
For deserialization, there is also the possibility to simply use NaN to specify
underflowing and overflowing situations. This can be configured as:
const cbot = Cbot.getInstance({
numberOverflowStrategy: {
onDeserialize: OnDeserializeOverflow.RETURN_NAN
}
});
Temporal API Support
Because the JavaScript Temporal API is finally emerging, the implementation is also using it as the default option. However, because the support is still experimental and requires the use of polyfills, a few considerations are needed.
Configuration
In order to use Temporal API it needs to be enabled as:
const cbot = Cbot.getInstance({
temporalApiEnabled: true
})
If the Temporal API is not available, then an error will be thrown.
Using Polyfills
Temporal API has been tested with (when writing this) using package
temporal-polyfill (0.3.2) and works as expected.
In this package the library is imported as:
import 'temporal-polyfill/global';
Note that import order matters. The Temporal polyfill must be imported always first, or you will get weird errors. For instance, if you get an error like this:
Inconsistent Meta-class declaration detected for type 'PlainDate'. Did you use 'A'-type without Meta-class declaration as value type?
Then the import happened too late and must be done earlier.
Binary Arrays
In JavaScript, the Uint8Array type is considered the binary type. If
binary support is needed, special consideration is required when creating a
Cbot instance, as JavaScript does not have a universal Base64 converter.
Instead, each environment has its own implementations.
Configuration
For instance, in a Node environment, the Cbot instance must be configured as:
const cbot = Cbot.getInstance({
typedArrayCoders: {
uint8ArrayCoder: {
encode: (value:Uint8Array) => Buffer.from(value).toString('base64'),
decode: (value:string) => Uint8Array.from(Buffer.from(value, 'base64'))
}
}
});
And in a browser as:
const cbot = Cbot.getInstance({
typedArrayCoders: {
uint8ArrayCoder: {
encode: (value: Uint8Array) => {
let binaryStr = "";
for (let i = 0; i < value.length; i++) {
binaryStr += String.fromCharCode(value[i]);
}
return btoa(binaryStr);
},
decode: (value: string) => {
const binary = atob(value);
const len = binary.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary.charCodeAt(i);
}
return bytes;
}
}
}
});