Skip to content

fix: replace node buffers with uint8arrays #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .aegir.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict'

module.exports = {
webpack: {
node: {
// this is needed until protocol-buffers stops using node core APIs in browser code
os: true,
Buffer: true
}
}
}
14 changes: 13 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ os:
- osx
- windows

script: npx nyc -s npm run test -- --bail
script: npx nyc -s npm run test:node -- --bail
after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov

jobs:
Expand All @@ -26,5 +26,17 @@ jobs:
- npx aegir dep-check
- npm run lint

- stage: test
name: chrome
addons:
chrome: stable
script: npx aegir test -t browser -t webworker

- stage: test
name: firefox
addons:
firefox: latest
script: npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless

notifications:
email: false
4 changes: 2 additions & 2 deletions bench/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const { Buffer } = require('buffer')
const Benchmark = require('benchmark')
if (typeof window !== 'undefined') {
window.Benchmark = Benchmark
Expand All @@ -13,11 +12,12 @@ const proto = require('./bench.proto')
const messages = protobuf(proto)
const messagesBuf = protons(proto)
const messagesNpm = protonsNpm(proto)
const uint8ArrayFromString = require('uint8arrays/from-string')

const EXAMPLE = {
foo: 'hello',
hello: 42,
payload: Buffer.from('a'),
payload: uint8ArrayFromString('a'),
meh: {
b: {
tmp: {
Expand Down
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,27 @@
"url": "https://github.com/ipfs/protons"
},
"dependencies": {
"buffer": "^5.5.0",
"protocol-buffers-schema": "^3.3.1",
"signed-varint": "^2.0.1",
"uint8arrays": "^1.0.0",
"varint": "^5.0.0"
},
"devDependencies": {
"ipfs-utils": "^2.3.0",
"aegir": "^21.4.0",
"aegir": "^25.0.0",
"benchmark": "^2.1.4",
"protocol-buffers": "^4.1.0",
"protons": "^1.0.0",
"tape": "^4.8.0"
},
"scripts": {
"test": "tape test/*.js",
"build": "aegir build",
"test": "aegir test",
"test:browser": "aegir test --target browser",
"test:node": "aegir test --target node",
"lint": "aegir lint",
"release": "aegir release --test=false",
"release-minor": "aegir release --type minor --test=false",
"release-major": "aegir release --type major --test=false",
"release": "aegir release",
"release-minor": "aegir release --type minor",
"release-major": "aegir release --type major",
"build": "aegir build",
"bench": "node bench"
},
"bugs": {
Expand Down
47 changes: 26 additions & 21 deletions src/compile/decode.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint max-depth: 1 */
'use strict'

var varint = require('varint')
var defined = require('./utils').defined
const varint = require('varint')
const defined = require('./utils').defined

function toSentenceCase (string) {
return `${string.substring(0, 1).toUpperCase()}${string.substring(1)}`
Expand Down Expand Up @@ -60,18 +60,18 @@ function addPropertyAccessors (obj, name, value, defaultValue) {
}

function compileDecode (m, resolve, enc) {
var requiredFields = []
var fields = {}
var oneofFields = []
var vals = []
const requiredFields = []
const fields = {}
const oneofFields = []
const vals = []

for (var i = 0; i < enc.length; i++) {
var field = m.fields[i]
const field = m.fields[i]

fields[field.tag] = i

var def = field.options && field.options.default
var resolved = resolve(field.type, m.id, false)
const def = field.options && field.options.default
const resolved = resolve(field.type, m.id, false)
vals[i] = [def, resolved && resolved.values]

m.fields[i].packed = field.repeated && field.options && field.options.packed && field.options.packed !== 'false'
Expand All @@ -85,12 +85,12 @@ function compileDecode (m, resolve, enc) {
}
}

function decodeField (e, field, obj, buf, offset, i) {
var name = field.name
function decodeField (e, field, obj, buf, dataView, offset, i) {
const name = field.name

if (field.oneof) {
// clear already defined oneof fields
var props = Object.keys(obj)
const props = Object.keys(obj)
for (var j = 0; j < props.length; j++) {
if (oneofFields.indexOf(props[j]) > -1) {
const sentenceCase = toSentenceCase(props[j])
Expand All @@ -106,10 +106,10 @@ function compileDecode (m, resolve, enc) {
let value

if (e.message) {
var len = varint.decode(buf, offset)
const len = varint.decode(buf, offset)
offset += varint.decode.bytes

var decoded = e.decode(buf, offset, offset + len)
const decoded = e.decode(buf, dataView, offset, offset + len)

if (field.map) {
value = obj[name] || {}
Expand All @@ -123,19 +123,20 @@ function compileDecode (m, resolve, enc) {
} else {
if (field.repeated) {
value = obj[name] || []
value.push(e.decode(buf, offset))
value.push(e.decode(buf, dataView, offset))
} else {
value = e.decode(buf, offset)
value = e.decode(buf, dataView, offset)
}
}

addPropertyAccessors(obj, name, value)

offset += e.decode.bytes

return offset
}

return function decode (buf, offset, end) {
return function decode (buf, view, offset, end) {
if (offset == null) {
offset = 0
}
Expand All @@ -148,6 +149,10 @@ function compileDecode (m, resolve, enc) {
throw new Error('Decoded message is not valid')
}

if (!view) {
view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
}

var oldOffset = offset
var obj = {}
var field
Expand Down Expand Up @@ -223,7 +228,7 @@ function compileDecode (m, resolve, enc) {
var i = fields[tag]

if (i == null) {
offset = skip(prefix & 7, buf, offset)
offset = skip(prefix & 7, buf, view, offset)
continue
}

Expand All @@ -236,16 +241,16 @@ function compileDecode (m, resolve, enc) {
packedEnd += offset

while (offset < packedEnd) {
offset = decodeField(e, field, obj, buf, offset, i)
offset = decodeField(e, field, obj, buf, view, offset, i)
}
} else {
offset = decodeField(e, field, obj, buf, offset, i)
offset = decodeField(e, field, obj, buf, view, offset, i)
}
}
}
}

var skip = function (type, buffer, offset) {
var skip = function (type, buffer, view, offset) {
switch (type) {
case 0:
varint.decode(buffer, offset)
Expand Down
67 changes: 35 additions & 32 deletions src/compile/encode.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
'use strict'
const { Buffer } = require('buffer')

var defined = require('./utils').defined
var varint = require('varint')

function compileEncode (m, resolve, enc, oneofs, encodingLength) {
var oneofsKeys = Object.keys(oneofs)
var encLength = enc.length
var ints = {}
for (var i = 0; i < encLength; i++) {
const oneofsKeys = Object.keys(oneofs)
const encLength = enc.length
const ints = {}
for (let i = 0; i < encLength; i++) {
ints[i] = {
p: varint.encode(m.fields[i].tag << 3 | 2),
h: varint.encode(m.fields[i].tag << 3 | enc[i].type)
}

var field = m.fields[i]
const field = m.fields[i]
m.fields[i].packed = field.repeated && field.options && field.options.packed && field.options.packed !== 'false'
}

function encodeField (buf, offset, h, e, packed, innerVal) {
var j = 0
function encodeField (buf, view, offset, h, e, packed, innerVal) {
let j = 0
if (!packed) {
for (j = 0; j < h.length; j++) {
buf[offset++] = h[j]
Expand All @@ -30,28 +30,30 @@ function compileEncode (m, resolve, enc, oneofs, encodingLength) {
offset += varint.encode.bytes
}

e.encode(innerVal, buf, offset)
e.encode(innerVal, buf, view, offset)

return offset + e.encode.bytes
}

return function encode (obj, buf, offset) {
if (offset == null) {
offset = 0
}
return function encode (obj, buf, view, offset = 0) {
if (buf == null) {
buf = Buffer.allocUnsafe(encodingLength(obj))
buf = new Uint8Array(encodingLength(obj))
}

var oldOffset = offset
var objKeys = Object.keys(obj)
var i = 0
if (view == null) {
view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
}

const oldOffset = offset
const objKeys = Object.keys(obj)
let i = 0

// oneof checks

var match = false
let match = false
for (i = 0; i < oneofsKeys.length; i++) {
var name = oneofsKeys[i]
var prop = oneofs[i]
const name = oneofsKeys[i]
const prop = oneofs[i]
if (objKeys.indexOf(prop) > -1) {
if (match) {
throw new Error('only one of the properties defined in oneof ' + name + ' can be set')
Expand All @@ -62,24 +64,24 @@ function compileEncode (m, resolve, enc, oneofs, encodingLength) {
}

for (i = 0; i < encLength; i++) {
var e = enc[i]
var field = m.fields[i] // was f
var val = obj[field.name]
var j = 0
const e = enc[i]
const field = m.fields[i] // was f
let val = obj[field.name]
let j = 0

if (!defined(val)) {
if (field.required) {
throw new Error(field.name + ' is required')
}
continue
}
var p = ints[i].p
var h = ints[i].h
const p = ints[i].p
const h = ints[i].h

var packed = field.packed
const packed = field.packed

if (field.map) {
var tmp = Object.keys(val)
const tmp = Object.keys(val)
for (j = 0; j < tmp.length; j++) {
tmp[j] = {
key: tmp[j],
Expand All @@ -90,7 +92,7 @@ function compileEncode (m, resolve, enc, oneofs, encodingLength) {
}

if (packed) {
var packedLen = 0
let packedLen = 0
for (j = 0; j < val.length; j++) {
if (!Object.prototype.hasOwnProperty.call(val, j)) {
continue
Expand All @@ -109,16 +111,17 @@ function compileEncode (m, resolve, enc, oneofs, encodingLength) {
}

if (field.repeated) {
var innerVal
let innerVal
for (j = 0; j < val.length; j++) {
innerVal = val[j]
if (!defined(innerVal)) {
continue
}
offset = encodeField(buf, offset, h, e, packed, innerVal)

offset = encodeField(buf, view, offset, h, e, packed, innerVal)
}
} else {
offset = encodeField(buf, offset, h, e, packed, val)
offset = encodeField(buf, view, offset, h, e, packed, val)
}
}

Expand Down
Loading