Coder
Data encoder and decoder that cares about data types.
Why do I need Coder?
Coder encodes javascript data into a buffer and decodes it back. Therefore data can be sent over the network without losing data types.
- Supports a lot of types out of the box
- is extendable
I can do that with JSON, right?
JSON is great, except it doesn’t support a lot of types.
const date = new Date();
const string = JSON.stringify(date); // "2020-02-13T13:16:43.096Z"
JSON.parse(string); // SyntaxErrorIn comparison Coder supports a lot of different types by default so your data will have the same type after decoding.
import { coder } from "https://deno.land/x/coder/mod.ts";
const date = new Date();
const buffer = coder.encode(date); // ArrayBuffer
coder.decode(buffer); // Date()But there is messagepack and protocol buffers, right?
Yes, and this project is inspired by messagepack. But Coder is specifically designed between comunicating between client- and server-side javascript. Therefore it only cares about javascript types.
Usage
import { coder } from "https://deno.land/x/coder/mod.ts";
const date = new Date();
const buffer = coder.encode(data);
coder.decode(buffer); // Date()Supported types
Coder supports lots of types out of the box:
- null
- undefined
- NaN
- Infinity and -Infinity
- boolean
- number
- BigInt
- string
- Object
- Array
- Date
- RegExp
- Error
- Set
- Map
It needs to be discussed what additional types should be supported by default. Some possible candidates are:
- AggregateError
- EvalError
- InternalError
- RangeError
- ReferenceError
- SyntaxError
- TypeError
- URIError
- Symbol
- Int8Array
- Uint8Array
- Uint8ClampedArray
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
- BigInt64Array
- BigUint64Array
- DataView
Custom DataType Definition
Coder can easily be extended with custom DataTypes.
Example:
1. Define Custom DataType
// SymbolDataType.ts
import { DataType, Decoder, Encoder } from "https://deno.land/x/coder/mod.ts";
export class SymbolDataType extends DataType {
// The test method returns true if data should be decoded for that type
test(data: unknown) {
return typeof data === "Symbol";
},
// The encode method transforms the data into a buffer
encode(encoder: Encoder, data: Symbol) {
const description = data.description; // get data to encode
const dataBuffer = encoder.stringToBuffer(description); // convert description to buffer
const lengthBuffer = encoder.uInt8ToBuffer(dataBuffer.byteLength); // convert length to buffer
return encoder.combineBuffers(lengthBuffer, dataBuffer); // return combined buffer
},
// The decode method transforms the buffer back to a value
decode(decoder: Decoder) {
const length = decoder.stepUint8(); // get length
const description = decoder.stepString(length); // get description
return Symbol(description); // create Symbol with description
},
};2. Set Custom DataType
There are 16 slots reserved for custom DataTypes: 0xf0-0xff. Chose a free
one and set the DataType.
import { coder } from "https://deno.land/x/coder/mod.ts";
// import custom DataType
import { SymbolDataType } from "./path/to/SymbolDataType.ts";
// set custom DataType
coder.set(0xf0, SymbolDataType);That’s it! Now Symbols will be encoded and decoded.
3. Use Custom DataType
const data = { mySymbol: Symbol("foo") };
const buffer = coder.encode(data);
coder.decoder(buffer); // { mySymbol: Symbol(foo) }