protocol-buffers-encodings
Version:
Base encodings for protocol-buffers
288 lines (252 loc) • 6.49 kB
JavaScript
var varint = require('varint')
var svarint = require('signed-varint')
var b4a = require('b4a')
exports.make = encoder
exports.name = function (enc) {
var keys = Object.keys(exports)
for (var i = 0; i < keys.length; i++) {
if (exports[keys[i]] === enc) return keys[i]
}
return null
}
exports.skip = function (type, buffer, offset) {
switch (type) {
case 0:
varint.decode(buffer, offset)
return offset + varint.decode.bytes
case 1:
return offset + 8
case 2:
var len = varint.decode(buffer, offset)
return offset + varint.decode.bytes + len
case 3:
case 4:
throw new Error('Groups are not supported')
case 5:
return offset + 4
}
throw new Error('Unknown wire type: ' + type)
}
exports.bytes = encoder(2,
function encode (val, buffer, offset) {
var oldOffset = offset
var len = bufferLength(val)
varint.encode(len, buffer, offset)
offset += varint.encode.bytes
if (b4a.isBuffer(val)) b4a.copy(val, buffer, offset)
else b4a.write(buffer, val, offset, len)
offset += len
encode.bytes = offset - oldOffset
return buffer
},
function decode (buffer, offset) {
var oldOffset = offset
var len = varint.decode(buffer, offset)
offset += varint.decode.bytes
var val = buffer.subarray(offset, offset + len)
offset += val.length
decode.bytes = offset - oldOffset
return val
},
function encodingLength (val) {
var len = bufferLength(val)
return varint.encodingLength(len) + len
}
)
exports.string = encoder(2,
function encode (val, buffer, offset) {
var oldOffset = offset
var len = b4a.byteLength(val)
varint.encode(len, buffer, offset, 'utf-8')
offset += varint.encode.bytes
b4a.write(buffer, val, offset, len)
offset += len
encode.bytes = offset - oldOffset
return buffer
},
function decode (buffer, offset) {
var oldOffset = offset
var len = varint.decode(buffer, offset)
offset += varint.decode.bytes
var val = b4a.toString(buffer, 'utf-8', offset, offset + len)
offset += len
decode.bytes = offset - oldOffset
return val
},
function encodingLength (val) {
var len = b4a.byteLength(val)
return varint.encodingLength(len) + len
}
)
exports.bool = encoder(0,
function encode (val, buffer, offset) {
buffer[offset] = val ? 1 : 0
encode.bytes = 1
return buffer
},
function decode (buffer, offset) {
var bool = buffer[offset] > 0
decode.bytes = 1
return bool
},
function encodingLength () {
return 1
}
)
exports.int32 = encoder(0,
function encode (val, buffer, offset) {
varint.encode(val < 0 ? val + 4294967296 : val, buffer, offset)
encode.bytes = varint.encode.bytes
return buffer
},
function decode (buffer, offset) {
var val = varint.decode(buffer, offset)
decode.bytes = varint.decode.bytes
return val > 2147483647 ? val - 4294967296 : val
},
function encodingLength (val) {
return varint.encodingLength(val < 0 ? val + 4294967296 : val)
}
)
exports.int64 = encoder(0,
function encode (val, buffer, offset) {
if (val < 0) {
var last = offset + 9
varint.encode(val * -1, buffer, offset)
offset += varint.encode.bytes - 1
buffer[offset] = buffer[offset] | 0x80
while (offset < last - 1) {
offset++
buffer[offset] = 0xff
}
buffer[last] = 0x01
encode.bytes = 10
} else {
varint.encode(val, buffer, offset)
encode.bytes = varint.encode.bytes
}
return buffer
},
function decode (buffer, offset) {
var val = varint.decode(buffer, offset)
if (val >= Math.pow(2, 63)) {
var limit = 9
while (buffer[offset + limit - 1] === 0xff) limit--
limit = limit || 9
var subset = b4a.allocUnsafe(limit)
b4a.copy(buffer, subset, 0, offset, offset + limit)
subset[limit - 1] = subset[limit - 1] & 0x7f
val = -1 * varint.decode(subset, 0)
decode.bytes = 10
} else {
decode.bytes = varint.decode.bytes
}
return val
},
function encodingLength (val) {
return val < 0 ? 10 : varint.encodingLength(val)
}
)
exports.sint32 =
exports.sint64 = encoder(0,
svarint.encode,
svarint.decode,
svarint.encodingLength
)
exports.uint32 =
exports.uint64 =
exports.enum =
exports.varint = encoder(0,
varint.encode,
varint.decode,
varint.encodingLength
)
// we cannot represent these in javascript so we just use buffers
exports.fixed64 =
exports.sfixed64 = encoder(1,
function encode (val, buffer, offset) {
b4a.copy(val, buffer, offset)
encode.bytes = 8
return buffer
},
function decode (buffer, offset) {
var val = buffer.subarray(offset, offset + 8)
decode.bytes = 8
return val
},
function encodingLength () {
return 8
}
)
exports.double = encoder(1,
function encode (val, buffer, offset) {
b4a.writeDoubleLE(buffer, val, offset)
encode.bytes = 8
return buffer
},
function decode (buffer, offset) {
var val = b4a.readDoubleLE(buffer, offset)
decode.bytes = 8
return val
},
function encodingLength () {
return 8
}
)
exports.fixed32 = encoder(5,
function encode (val, buffer, offset) {
b4a.writeUInt32LE(buffer, val, offset)
encode.bytes = 4
return buffer
},
function decode (buffer, offset) {
var val = b4a.readUInt32LE(buffer, offset)
decode.bytes = 4
return val
},
function encodingLength () {
return 4
}
)
exports.sfixed32 = encoder(5,
function encode (val, buffer, offset) {
b4a.writeInt32LE(buffer, val, offset)
encode.bytes = 4
return buffer
},
function decode (buffer, offset) {
var val = b4a.readInt32LE(buffer, offset)
decode.bytes = 4
return val
},
function encodingLength () {
return 4
}
)
exports.float = encoder(5,
function encode (val, buffer, offset) {
b4a.writeFloatLE(buffer, val, offset)
encode.bytes = 4
return buffer
},
function decode (buffer, offset) {
var val = b4a.readFloatLE(buffer, offset)
decode.bytes = 4
return val
},
function encodingLength () {
return 4
}
)
function encoder (type, encode, decode, encodingLength) {
encode.bytes = decode.bytes = 0
return {
type: type,
encode: encode,
decode: decode,
encodingLength: encodingLength
}
}
function bufferLength (val) {
return b4a.isBuffer(val) ? val.length : b4a.byteLength(val)
}