From 61a0a9c0fe5b697c541d91748d43ec9f98565f9a Mon Sep 17 00:00:00 2001 From: Nul-led Date: Mon, 20 Jan 2025 17:53:54 +0100 Subject: [PATCH 1/2] docs: add new encoding primitives --- pages/state/schema.mdx | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/pages/state/schema.mdx b/pages/state/schema.mdx index 838ac6de..e92f0287 100644 --- a/pages/state/schema.mdx +++ b/pages/state/schema.mdx @@ -96,20 +96,34 @@ export class MyRoom extends Room { ### Primitive types + + **Some types are only available for JavaScript SDK:** `cstring`, `bigUint64`, `bigInt64`, `varUint`, `varInt`, `varBigUint`, `varBigInt`, `varFloat32`, `varFloat64` + + **`cstring` type requires the platform to supply a TextEncoder (and TextDecoder) implementation.** You may supply a polyfill yourself. + + - `string`: utf8 string type - `boolean`: `true` or `false` - `number`: auto-detects the number type to use. (may use one extra byte when encoding) - `uint8`, `uint16`, `uint32`, `uint64`: unsigned number types. - `int8`, `int16`, `int32`, `int64`: signed number types. - `float32`, `float64`: floating-point number types. +- `cstring`: utf8 null-terminated string type. +- `bigUint64`, `bigInt64`: unsigned / signed 64-bit bigint type. +- `varUint`, `varInt`: unsigned / signed variable-length integer type. (encoded with [LEB128](https://en.wikipedia.org/wiki/LEB128)) +- `varBigUint`, `varBigInt`: unsigned / signed variable-length bigint type. (encoded with [LEB128](https://en.wikipedia.org/wiki/LEB128)) +- `varFloat32`, `varFloat64`: variable-length floating-point number types. (encoded with [LEB128](https://en.wikipedia.org/wiki/LEB128)) #### Table of types and their limitations | Type | Description | Limitation | |------|-------------|------------| -| `"string"` | utf8 strings | maximum byte size of `4294967295` | -| `"number"` | also known as "varint". Auto-detects the number type to use. (may use one extra byte when encoding) | `0` to `18446744073709551615` | +| `"string"` | length-prefixed utf8 strings | maximum byte size of `4294967295` | +| `"cstring"` | null-terminated utf8 strings | string must not contain a null-byte ("\x00") | +| `"number"` | also known as "variable length encoding". Auto-detects the number type to use. (may use one extra byte when encoding to identify the type) | `5e-324` to `5e+324` (float64 limits) | | `"boolean"` | `true` or `false` | `0` or `1` | +| `"int64"` and `"uint64"` | JavaScript numbers are 64 bit floats and thus cannot represent full 64 bit integers safely | The minimum/maximum integer that can be safely represented by float64 is `-9007199254740991` to `9007199254740991` (53 bits of precision) | + Specialized number types: @@ -121,10 +135,22 @@ Specialized number types: | `"uint16"` | unsigned 16-bit integer | `0` to `65535` | | `"int32"` | signed 32-bit integer | `-2147483648` to `2147483647` | | `"uint32"` | unsigned 32-bit integer | `0` to `4294967295` | -| `"int64"` | signed 64-bit integer | `-9223372036854775808` to `9223372036854775807` | -| `"uint64"` | unsigned 64-bit integer | `0` to `18446744073709551615` | +| `"int64"` | signed 64-bit integer (`number` type) | `-2^53-1 (-9007199254740991)` to `2^53-1 (9007199254740991)` (safely) | +| `"uint64"` | unsigned 64-bit integer (`number` type) | `0` to `2^53-1 (9007199254740991)` (safely) | | `"float32"` | single-precision floating-point number | `-3.40282347e+38` to `3.40282347e+38`| | `"float64"` | double-precision floating-point number | `-1.7976931348623157e+308` to `1.7976931348623157e+308` | +| `"bigInt64"` | signed 64-bit integer (`bigint` type) | `-2^63 (-9223372036854775808)` to `2^63-1 (9223372036854775807)` | +| `"bigUint64"` | unsigned 64-bit integer (`bigint` type) | `0` to `2^64-1 (18446744073709551615)` | + +Variable length number types: +| Type | Description | Limitation | Size (Bytes) | +|------|-------------|------------|--------------| +| `"varInt"` | signed variable-length encoded integer (`number` type) | -2147483648 to 2147483647 (safely) | 1 - 8 (depending on bits used) | +| `"varUint"` | unsigned variable-length encoded integer (`number` type) | 0 to 4294967296 (safely) | 1 - 8 (depending on bits used) | +| `"varBigInt"` | signed variable-length encoded integer (`bigint` type) | limitations based on platforms bigint implementation | 1 - ? (depending on the bits used) | +| `"varBigUint"` | unsigned variable-length encoded integer (`bigint` type) | limitations based on platforms bigint implementation | 1 - ? (depending on the bits used) | +| `"varFloat32"` | single-precision variable-length encoded floating-point number | `-3.40282347e+38` to `3.40282347e+38`| 2 - 6 (depending on bits used) | +| `"varFloat64"` | double-precision variable-length encoded floating-point number | `-1.7976931348623157e+308` to `1.7976931348623157e+308` | 2 - 10 (depending on the bits used) | ### `Schema` type @@ -831,6 +857,7 @@ This is particularly useful for native-compiled targets, such as C#, C++, Haxe, ## Inheritance support The collection types (`ArraySchema`, `MapSchema`, etc) must hold items of the same type. They support inherited types from the same base instance. +These inherited types may define their own serialized fields. The following example is supported: From a85f92c48f5da3a2b1759b62a634ded5d06dc52e Mon Sep 17 00:00:00 2001 From: Nul-led Date: Mon, 20 Jan 2025 17:54:11 +0100 Subject: [PATCH 2/2] docs: update best practices --- pages/state/best-practices.mdx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pages/state/best-practices.mdx b/pages/state/best-practices.mdx index 0ce7bebe..44cf3c93 100644 --- a/pages/state/best-practices.mdx +++ b/pages/state/best-practices.mdx @@ -2,10 +2,9 @@ ## Limitations and Best practices -- Each `Schema` structure can hold up to `64` fields. If you need more fields, use nested `Schema` structures. -- `NaN` or `null` numbers are encoded as `0` -- `null` strings are encoded as `""` -- `Infinity` numbers are encoded as `Number.MAX_SAFE_INTEGER` +- Each `Schema` structure can hold up to `64` serialized fields. If you need more fields, use nested `Schema` structures. +- `NaN` and `Infinity` are encoded as `0` (integer encoding only) +- `null` strings are encoded as `""` (both "string" and "cstring" encoding) - Multi-dimensional arrays are not supported. [See how to use 1D arrays as multi-dimensional](https://softwareengineering.stackexchange.com/questions/212808/treating-a-1d-data-structure-as-2d-grid/212813#212813) - `@colyseus/schema` encoding order is based on field definition order. - Both encoder (server) and decoder (client) must have same schema definition.