Skip to main content
Deno 2 is finally here 🎉️
Learn more

Coder

Data encoder and decoder that cares about data types.

Why do I need Coder?

Coder encodes javacript data into a buffer and decodes it back. Therefore data can be sent over the network without losing data types.

  • Works 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) // SyntaxError

In 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 javacript 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:

It needs to be discussed what additional types should be supported by default. Some possible candidates are:

Custom DataType Definition

Coder can easily be extended with custom DataTypes.

Example:

1. Define Custom DataType

// SymbolDataType.ts
import { DataType, Encoder, Decoder } from "https://deno.land/x/coder/mod.ts"

export const SymbolDataType = {
  // The test method returns true if data should be decoded for that type.
  test(data: any) { return typeof data === "Symbol" },
  // The encode method transforms the data into a buffer, where the first byte must be the type of the DataType.
  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) // create a buffer where the first byte must be the type id byte
  },
  // 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. Register Custom DataType

import { coder } from "https://deno.land/x/coder/mod.ts"
// import custom DataType
import { SymbolDataType } from "./path/to/SymbolDataType.ts"
// Register custom DataType
coder.register(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) }