95 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict'
 | 
						|
 | 
						|
var bindexOf = require('buffer-indexof')
 | 
						|
 | 
						|
var equalSign = new Buffer('=')
 | 
						|
 | 
						|
module.exports = function (opts) {
 | 
						|
  var binary = opts ? opts.binary : false
 | 
						|
  var that = {}
 | 
						|
 | 
						|
  that.encode = function (data, buf, offset) {
 | 
						|
    if (!data) data = {}
 | 
						|
    if (!offset) offset = 0
 | 
						|
    if (!buf) buf = new Buffer(that.encodingLength(data) + offset)
 | 
						|
 | 
						|
    var oldOffset = offset
 | 
						|
    var keys = Object.keys(data)
 | 
						|
 | 
						|
    if (keys.length === 0) {
 | 
						|
      buf[offset] = 0
 | 
						|
      offset++
 | 
						|
    }
 | 
						|
 | 
						|
    keys.forEach(function (key) {
 | 
						|
      var val = data[key]
 | 
						|
      var oldOffset = offset
 | 
						|
      offset++
 | 
						|
 | 
						|
      if (val === true) {
 | 
						|
        offset += buf.write(key, offset)
 | 
						|
      } else if (Buffer.isBuffer(val)) {
 | 
						|
        offset += buf.write(key + '=', offset)
 | 
						|
        var len = val.length
 | 
						|
        val.copy(buf, offset, 0, len)
 | 
						|
        offset += len
 | 
						|
      } else {
 | 
						|
        offset += buf.write(key + '=' + val, offset)
 | 
						|
      }
 | 
						|
 | 
						|
      buf[oldOffset] = offset - oldOffset - 1
 | 
						|
    })
 | 
						|
 | 
						|
    that.encode.bytes = offset - oldOffset
 | 
						|
    return buf
 | 
						|
  }
 | 
						|
 | 
						|
  that.decode = function (buf, offset, len) {
 | 
						|
    if (!offset) offset = 0
 | 
						|
    if (!Number.isFinite(len)) len = buf.length
 | 
						|
    var data = {}
 | 
						|
    var oldOffset = offset
 | 
						|
 | 
						|
    while (offset < len) {
 | 
						|
      var b = decodeBlock(buf, offset)
 | 
						|
      var i = bindexOf(b, equalSign)
 | 
						|
      offset += decodeBlock.bytes
 | 
						|
 | 
						|
      if (b.length === 0) continue // ignore: most likely a single zero byte
 | 
						|
      if (i === -1) data[b.toString().toLowerCase()] = true
 | 
						|
      else if (i === 0) continue // ignore: invalid key-length
 | 
						|
      else {
 | 
						|
        var key = b.slice(0, i).toString().toLowerCase()
 | 
						|
        if (key in data) continue // ignore: overwriting not allowed
 | 
						|
        data[key] = binary ? b.slice(i + 1) : b.slice(i + 1).toString()
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    that.decode.bytes = offset - oldOffset
 | 
						|
    return data
 | 
						|
  }
 | 
						|
 | 
						|
  that.encodingLength = function (data) {
 | 
						|
    if (!data) return 1 // 1 byte (single empty byte)
 | 
						|
    var keys = Object.keys(data)
 | 
						|
    if (keys.length === 0) return 1 // 1 byte (single empty byte)
 | 
						|
    return keys.reduce(function (total, key) {
 | 
						|
      var val = data[key]
 | 
						|
      total += Buffer.byteLength(key) + 1 // +1 byte to store field length
 | 
						|
      if (Buffer.isBuffer(val)) total += val.length + 1 // +1 byte to fit equal sign
 | 
						|
      else if (val !== true) total += Buffer.byteLength(String(val)) + 1 // +1 byte to fit equal sign
 | 
						|
      return total
 | 
						|
    }, 0)
 | 
						|
  }
 | 
						|
 | 
						|
  return that
 | 
						|
}
 | 
						|
 | 
						|
function decodeBlock (buf, offset) {
 | 
						|
  var len = buf[offset]
 | 
						|
  var to = offset + 1 + len
 | 
						|
  var b = buf.slice(offset + 1, to > buf.length ? buf.length : to)
 | 
						|
  decodeBlock.bytes = len + 1
 | 
						|
  return b
 | 
						|
}
 |