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;
      }
    }
  }
});