# dec0de

> Protocol handler based on generators :stars:

Latest version **0.2.0** (published 2016-08-02) · ISC license · 0 weekly downloads

## Install

```sh
npm install dec0de
pnpm add dec0de
yarn add dec0de
bun add dec0de
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2016-08-02 |
| First published | 2016-08-01 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 1 |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 4 |
| Author | Boris Okunskiy |
| Maintainers | inca |
| Keywords | protocol, decoder, handler, parser, socket, network |

## Links

- npm: https://www.npmjs.com/package/dec0de
- Repository: https://github.com/inca/dec0de
- Homepage: https://github.com/inca/dec0de#readme
- Issues: https://github.com/inca/dec0de/issues
- npm.io page: https://npm.io/package/dec0de

## Dependencies (1)

- [debug](https://npm.io/package/debug.md) ^2.2.0

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 0.2.0 (latest) — 2016-08-02
- 0.1.2 — 2016-08-02
- 0.1.1 — 2016-08-02
- 0.1.0 — 2016-08-01

## README

# dec0de

Protocol buffers handler/parser based on awesome ES6 generators.

## WTF? (What's That For?)

### The Problem

Handling low-level protocol data (e.g. received via socket or stream)
can be tricky b/c data is received in packets.

E.g. assume typical HTTP request line:

```
GET / HTTP/1.1\r\n
```

A typical server will have this code to accept requests:

```es6
server.on('connection', socket => {
  socket.on('data', data => {
    // handle buffers
  });
});
```

Each `data` is a buffer that contains _some_ request fragment.
It can contain the entire request line, it can contain only it's fragment
(e.g. `GET / HTTP`), it can contain more than that.
It can even be received char-by-char.

In order to handle protocols your server needs to:

  * accumulate buffers
  * maintain internal parsing states (typically, microstates for processing each token)
  * organize state changing and buffer consumption
  * provide a notion for "wait for data"
  * handle protocol expectations and throw errors

```es6
server.on('connection', socket => {

  // protocol messages output
  const out = new EventEmitter();

  // we need parser state
  let state = 'expect-http-status-line';

  // we need accumulated buffer for handling data
  // received via multiple 'data' event
  let remaining = Buffer.alloc(0);

  socket.on('data', data => {
    // accumulate buffer
    remaining = Buffer.concat([remaining, data]);
    // handle parser state
    switch (state) {
      case 'expect-http-status-line':
        // see if we have accumulated required data for this state
        const i = remaining.indexOf('\r\n');
        if (i === -1) {
          // we need more data
          return;
        }
        // extract protocol-specific data, emit it
        const line = remaining.slice(0, i);
        out.emit('request-line', line)
        // don't forget to consume stuff from buffer
        remaining = remaining.slice(i);
        // don't forget to enter next state
        state = 'expect-headers';
        // phew, we're done here
        break;
      // now handle more protocol parts (headers, body, etc) :(
    }
  });

});
```

In other words, there's a whole lot of cross-cutting concerns which can easily
make your incoming data handler an awful mix of I/O handling, state maintenance
and protocol-specific logic — error prone, unreadable and unmaintainable.

### The Solution

Meet dec0de — low-level abstraction for handling buffers and expectations.

Thanks to awesome ES6 generators our previous switch-case-based parser state
handler can be written in a single line:

```es6
function* decodeHttpRequest() {
  const line = yield buf => buf.indexOf('\r\n');
  // handle next protocol parts (headers, body, etc.)
}
```

Parsing state is maintained via generated iterators in a natural, readable and reliable manner.
Internally, dec0de will also handle memory-efficient buffer accumulation/consumption
and generator lifecycle (instantiate, pause and resume). All that's left for you is
to implement protocol handling logic.

Here's our previous example:

```es6
function* decodeHttpRequest() {
  const line = yield buf => buf.indexOf('\r\n');
  out.emit('request-line', line);
  // handle next protocol parts (headers, body, etc.)
}

server.on('connection', socket => {
  const decoder = new Decoder(decodeHttpRequest);
  socket.on('data', data => decoder.decode(data));
});
```

Please refer to [some tests](test/) for more examples.

## Usage

```
npm i --save dec0de
```

---
_Source: https://npm.io/package/dec0de · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
