| '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 | 
| } |