Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

msgpackr

Package Overview
Dependencies
Maintainers
1
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

msgpackr - npm Package Compare versions

Comparing version 0.2.2 to 0.3.0

tests/example5.json

8

index.js
exports.Packr = require('./pack').Packr
exports.Encoder = exports.Packr
let unpackModule = require('./unpack')

@@ -7,7 +8,12 @@ let extractor = tryRequire('msgpackr-extract')

exports.Unpackr = unpackModule.Unpackr
exports.Decoder = exports.Unpackr
exports.PackrStream = require('./stream').PackrStream
exports.UnpackrStream = require('./stream').UnpackrStream
let packr = new exports.Packr({ objectsAsMaps: true })
exports.EncoderStream = exports.PackrStream
exports.DecoderStream = exports.UnpackrStream
let packr = new exports.Packr({ useRecords: false })
exports.unpack = packr.unpack
exports.pack = packr.pack
exports.decode = packr.unpack
exports.encode = packr.pack

@@ -14,0 +20,0 @@ function tryRequire(moduleId) {

@@ -332,3 +332,23 @@ "use strict"

const writeObject = this.objectsAsMaps ? (object, safePrototype) => {
const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
let keys = Object.keys(object)
let length = keys.length
if (length < 0x10) {
target[position++] = 0x80 | length
} else if (length < 0x10000) {
target[position++] = 0xde
target[position++] = length >> 8
target[position++] = length & 0xff
} else {
target[position++] = 0xdf
targetView.setUint32(position, length)
position += 4
}
let key
for (let i = 0; i < length; i++) {
pack(key = keys[i])
pack(object[key])
}
} :
(object, safePrototype) => {
target[position++] = 0xde // always use map 16, so we can preallocate and set the length afterwards

@@ -348,2 +368,3 @@ let objectOffset = position - start

} :
/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster

@@ -350,0 +371,0 @@ (object, safePrototype) => {

6

package.json
{
"name": "msgpackr",
"author": "Kris Zyp",
"version": "0.2.2",
"version": "0.3.0",
"description": "Fast MessagePack implementation with extension for record structures",

@@ -15,3 +15,3 @@ "license": "MIT",

"scripts": {
"benchmark": "./tests/benchmark.js",
"benchmark": "node ./tests/benchmark.js",
"test": "./node_modules/.bin/mocha tests/test*.js -u tdd"

@@ -21,3 +21,3 @@ },

"optionalDependencies": {
"msgpackr-extract": "^0.1.1"
"msgpackr-extract": "^0.2.0"
},

@@ -24,0 +24,0 @@ "devDependencies": {

@@ -47,2 +47,5 @@ # msgpackr

## Alternate Terminology
If you prefer to use encoder/decode terminology, msgpackr exports aliases, so `decode` is equivalent to `unpack`, `encode` is `pack`, `Encoder` is `Packr`, `Decoder` is `Unpackr`, and `EncoderStream` and `DecoderStream` can be used as well.
## Browser Usage

@@ -53,6 +56,6 @@ Msgpackr works as standalone JavaScript as well, and runs on modern browsers. It includes a bundled script for ease of direct loading. For module-based development, it is recommended that you directly import the module of interest, to minimize dependencies that get pulled into your application:

```
(It is worth noting that while msgpackr works well in browsers, the MessagePack format itself is usually not an ideal format for web use. If you want compact data, brotli or gzip are most effective in compressing, and MessagePack's character frequency tends to defeat Huffman encoding used by these standard compression algorithms, resulting in less compact data than compressed JSON. The modern browser architecture is heavily optimized for parsing JSON from HTTP traffic, and it is difficult to achieve the same level of overall efficiency and ease with MessagePack.)
(It is worth noting that while msgpackr works well in modern browsers, the MessagePack format itself is usually not an ideal format for web use. If you want compact data, brotli or gzip are most effective in compressing, and MessagePack's character frequency tends to defeat Huffman encoding used by these standard compression algorithms, resulting in less compact data than compressed JSON. The modern browser architecture is heavily optimized for parsing JSON from HTTP traffic, and it is difficult to achieve the same level of overall efficiency and ease with MessagePack.)
## Record / Object Structures
There is a critical difference between maps (or dictionaries) that hold an arbitrary set of keys and values (JavaScript `Map` is designed for these), and records or object structures that have a well-defined set of fields which may have many instances using that same structure (most objects in JS). By using the record extension, this distinction is preserved in MessagePack and the encoding can reuse structures and not only provides better type preservation, but yield much more compact encodings and increase parsing/deserialization performance by 2-3x. Msgpackr automatically generates record definitions that are reused and referenced by objects with the same structure. There are a number of ways to use this to our advantage. For large object structures with repeating nested objects with similar structures, simply serializing with the record extension can yield benefits. To use the record structures extension, we create a new `Packr` instance. By default a new `Packr` instance will have the record extension enabled:
There is a critical difference between maps (or dictionaries) that hold an arbitrary set of keys and values (JavaScript `Map` is designed for these), and records or object structures that have a well-defined set of fields which may have many instances using that same structure (most objects in JS). By using the record extension, this distinction is preserved in MessagePack and the encoding can reuse structures and not only provides better type preservation, but yield much more compact encodings and increase parsing/deserialization performance by 2-3x. Msgpackr automatically generates record definitions that are reused and referenced by objects with the same structure. There are a number of ways to use this to our advantage. For large object structures with repeating nested objects with similar structures, simply serializing with the record extension can yield significant benefits. To use the record structures extension, we create a new `Packr` instance. By default a new `Packr` instance will have the record extension enabled:
```

@@ -67,3 +70,3 @@ import { Packr } from 'msgpackr';

When creating a new `Packr`, `PackrStream`, or `UnpackrStream` instance, we can enable or disable the record structure extension with the `objectsAsMaps` property. When this is `true`, the record structure extension will be disabled, and all objects will revert to being serialized using MessageMap `map`s, and all `map`s will be deserialized to JS `Object`s as properties (like the standalone `pack` and `unpack` functions).
When creating a new `Packr`, `PackrStream`, or `UnpackrStream` instance, we can enable or disable the record structure extension with the `useRecords` property. When this is `false`, the record structure extension will be disabled (standard/compatibility mode), and all objects will revert to being serialized using MessageMap `map`s, and all `map`s will be deserialized to JS `Object`s as properties (like the standalone `pack` and `unpack` functions).

@@ -90,4 +93,6 @@ ### Shared Record Structures

The following options properties can be provided to the Packr or Unpackr constructor:
* `objectsAsMaps` - Turning this on disables the record extension and stores JavaScript objects as MessagePack maps, and unpacks maps as JavaScript `Object`s.
* `useRecords` - Setting this to `false` disables the record extension and stores JavaScript objects as MessagePack maps, and unpacks maps as JavaScript `Object`s, which ensures compatibilty with other decoders.
* `structures` - Provides the array of structures that is to be used for record extension, if you want the structures saved and used again.
* `mapsAsObjects` - If `true`, this will decode MessagePack maps and JS `Object`s with the map entries decoded to object properties. If `false`, maps are decoded as JavaScript `Map`s. This is disabled by default if `useRecords` is enabled (which allows `Map`s to be preserved), and is enabled by default if `useRecords` is disabled.
* `variableMapSize` - This will use varying map size definition (fixmap, map16, map32) based on the number of keys when encoding data, which yields slightly more compact encodings (for small objects), but is typically 5-10% slower during encoding.

@@ -94,0 +99,0 @@ ## Performance

@@ -20,3 +20,3 @@ var msgpackr = tryRequire("..");

var pkg = require("../package.json");
var data = require("./example4.json");
var data = require("./example.json");
var packed = msgpack_lite && msgpack_lite.encode(data);

@@ -23,0 +23,0 @@ var expected = JSON.stringify(data);

@@ -33,3 +33,3 @@ //var inspector = require('inspector')

var fs = require('fs')
var sampleData = JSON.parse(fs.readFileSync(__dirname + '/example4.json'))
var sampleData = JSON.parse(fs.readFileSync(__dirname + '/example.json'))
} else {

@@ -98,3 +98,3 @@ var xhr = new XMLHttpRequest()

let structures = []
let packr = new Packr({ structures, objectsAsMaps: false })
let packr = new Packr({ structures, useRecords: true })
var serialized = packr.pack(data)

@@ -235,3 +235,3 @@ var deserialized = packr.unpack(serialized)

let structures = []
let packr = new Packr({ structures, objectsAsMaps: false })
let packr = new Packr({ structures, useRecords: true })
var serialized = packr.pack(data)

@@ -247,3 +247,3 @@ console.log('msgpackr size', serialized.length)

let structures = []
let packr = new Packr({ structures, objectsAsMaps: false })
let packr = new Packr({ structures, useRecords: true })

@@ -250,0 +250,0 @@ for (var i = 0; i < ITERATIONS; i++) {

@@ -20,3 +20,6 @@ "use strict"

let dataView
let defaultOptions = { objectsAsMaps: true }
let defaultOptions = {
useRecords: false,
mapsAsObjects: true
}
// the registration of the record definition extension (as "r")

@@ -38,2 +41,4 @@ const recordDefinition = currentExtensions[0x72] = (id) => {

constructor(options) {
if (options && options.useRecords === false && options.mapsAsObjects === undefined)
options.mapsAsObjects = true
Object.assign(this, options)

@@ -111,3 +116,3 @@ }

token -= 0x80
if (currentUnpackr.objectsAsMaps) {
if (currentUnpackr.mapsAsObjects) {
let object = {}

@@ -139,5 +144,5 @@ for (let i = 0; i < token; i++) {

}
if (srcStringEnd == 0 && length < 8 && srcEnd < 128) {
if (srcStringEnd == 0 && srcEnd < 120 && length < 16) {
// for small blocks, avoiding the overhead of the extract call is helpful
let string = simpleString(length)
let string = /*length < 16 ? */shortStringInJS(length)// : longStringInJS(length)
if (string != null)

@@ -422,3 +427,3 @@ return string

function readMap(length) {
if (currentUnpackr.objectsAsMaps) {
if (currentUnpackr.mapsAsObjects) {
let object = {}

@@ -439,14 +444,16 @@ for (let i = 0; i < length; i++) {

let fromCharCode = String.fromCharCode
/*function simpleString(length) {
function longStringInJS(length) {
let start = position
let bytes = new Array(length)
for (let i = 0; i < length; i++) {
const byte = src[position++];
if ((byte & 0x80) > 0) {
position -= i + 1
position = start
return
}
bytes[i] = byte
}
return asString.slice(start, position)
}*/
function simpleString(length) {
return fromCharCode.apply(String, bytes)
}
function shortStringInJS(length) {
if (length < 4) {

@@ -494,3 +501,3 @@ if (length < 2) {

let e = src[position++]
if ((e & 0x80) > 1) {
if ((e & 0x80) > 0) {
position -= 5

@@ -501,3 +508,3 @@ return

}
} else {
} else if (length < 8) {
let e = src[position++]

@@ -513,8 +520,79 @@ let f = src[position++]

if ((g & 0x80) > 0) {
position -= 3
position -= 7
return
}
return fromCharCode(a, b, c, d, e, f, g)
} else {
let e = src[position++]
let f = src[position++]
let g = src[position++]
let h = src[position++]
if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
position -= 8
return
}
if (length < 10) {
if (length === 8)
return fromCharCode(a, b, c, d, e, f, g, h)
else {
let i = src[position++]
if ((i & 0x80) > 0) {
position -= 9
return
}
return fromCharCode(a, b, c, d, e, f, g, h, i)
}
} else if (length < 12) {
let i = src[position++]
let j = src[position++]
if ((i & 0x80) > 0 || (j & 0x80) > 0) {
position -= 10
return
}
if (length < 11)
return fromCharCode(a, b, c, d, e, f, g, h, i, j)
let k = src[position++]
if ((k & 0x80) > 0) {
position -= 11
return
}
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
} else {
let i = src[position++]
let j = src[position++]
let k = src[position++]
let l = src[position++]
if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
position -= 12
return
}
if (length < 14) {
if (length === 12)
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
else {
let m = src[position++]
if ((m & 0x80) > 0) {
position -= 13
return
}
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
}
} else {
let m = src[position++]
let n = src[position++]
if ((m & 0x80) > 0 || (n & 0x80) > 0) {
position -= 14
return
}
if (length < 15)
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
let o = src[position++]
if ((o & 0x80) > 0) {
position -= 15
return
}
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
}
}
}
}

@@ -521,0 +599,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc