Skip to content

Commit

Permalink
custom BEB128 implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
devgru committed Jul 30, 2013
1 parent 8b54c4a commit c5cafcc
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 39 deletions.
32 changes: 32 additions & 0 deletions src/beb.coffee
@@ -0,0 +1,32 @@
###
BEB128 implementation. Tarantool uses BEB128 and calls it LEB128 somewhy.
Big-endian base-128 uses 7 bits for value and most significant bit (MSB) for flag
If flag is 1 — there is more bytes, continue reading.
So, 127 is 0x7f, 128 is 0x81 0x00, 129 is 0x81 0x01 and so on.
###

encode = (value) ->
bytes = []

bytes.push value >> 28 | 0x80 if value >= 1 << 28
bytes.push value >> 21 | 0x80 if value >= 1 << 21
bytes.push value >> 14 | 0x80 if value >= 1 << 14
bytes.push value >> 7 | 0x80 if value >= 1 << 7
bytes.push value & 0x7F

new Buffer bytes

decode = (buffer, position = 0) ->
value = 0
loop # stops after reading byte with MSB=0
byte = buffer[position++]
value = (value << 7) + (byte & 0x7F)
break unless byte & 0x80

value: value
nextIndex: position

module.exports =
encode: encode
decode: decode
6 changes: 3 additions & 3 deletions src/compose.coffee
@@ -1,4 +1,4 @@
leb = require './leb'
beb = require './beb'

module.exports = compose =
###
Expand All @@ -21,14 +21,14 @@ module.exports = compose =
stringField: (value) ->
# what about string encoding?
stringBuffer = new Buffer value, 'utf-8' # default
lengthBuffer = leb.encodeUInt32 stringBuffer.length
lengthBuffer = beb.encode stringBuffer.length

Buffer.concat [lengthBuffer, stringBuffer]

tuple: (tuple) ->
buffers = [compose.int32s tuple.length]
for field in tuple
buffers.push leb.encodeUInt32 field.length
buffers.push beb.encode field.length
buffers.push field

Buffer.concat buffers
Expand Down
34 changes: 0 additions & 34 deletions src/leb.coffee

This file was deleted.

4 changes: 2 additions & 2 deletions src/parse.coffee
@@ -1,4 +1,4 @@
leb = require './leb'
beb = require './beb'

module.exports = parse =
###
Expand Down Expand Up @@ -29,7 +29,7 @@ module.exports = parse =
fields = []

while count > 0
sizeLeb = leb.decodeUInt32 tuple, bytesRead
sizeLeb = beb.decode tuple, bytesRead
bytesRead = sizeLeb.nextIndex
size = sizeLeb.value
fields.push tuple.slice bytesRead, bytesRead += size
Expand Down
14 changes: 14 additions & 0 deletions test/beb.coffee
@@ -0,0 +1,14 @@
beb = require '../src/beb'

exports['encode'] = (test) ->
test.equalBuffer = (b1, b2) ->
@equal b1.toString('hex'), b2.toString('hex')
test.equalBuffer (new Buffer [0x80 | 1, 0]), beb.encode 128
test.equalBuffer (new Buffer [0x80 | 1, 1]), beb.encode 129
do test.done

exports['fuzz'] = (test) ->
for i in [0...(1<<15)] by 1<<5
test.equal i, beb.decode(beb.encode(i)).value
do test.done

0 comments on commit c5cafcc

Please sign in to comment.