You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.5 KiB

4 years ago
  1. 'use strict'
  2. var bindexOf = require('buffer-indexof')
  3. var equalSign = new Buffer('=')
  4. module.exports = function (opts) {
  5. var binary = opts ? opts.binary : false
  6. var that = {}
  7. that.encode = function (data, buf, offset) {
  8. if (!data) data = {}
  9. if (!offset) offset = 0
  10. if (!buf) buf = new Buffer(that.encodingLength(data) + offset)
  11. var oldOffset = offset
  12. var keys = Object.keys(data)
  13. if (keys.length === 0) {
  14. buf[offset] = 0
  15. offset++
  16. }
  17. keys.forEach(function (key) {
  18. var val = data[key]
  19. var oldOffset = offset
  20. offset++
  21. if (val === true) {
  22. offset += buf.write(key, offset)
  23. } else if (Buffer.isBuffer(val)) {
  24. offset += buf.write(key + '=', offset)
  25. var len = val.length
  26. val.copy(buf, offset, 0, len)
  27. offset += len
  28. } else {
  29. offset += buf.write(key + '=' + val, offset)
  30. }
  31. buf[oldOffset] = offset - oldOffset - 1
  32. })
  33. that.encode.bytes = offset - oldOffset
  34. return buf
  35. }
  36. that.decode = function (buf, offset, len) {
  37. if (!offset) offset = 0
  38. if (!Number.isFinite(len)) len = buf.length
  39. var data = {}
  40. var oldOffset = offset
  41. while (offset < len) {
  42. var b = decodeBlock(buf, offset)
  43. var i = bindexOf(b, equalSign)
  44. offset += decodeBlock.bytes
  45. if (b.length === 0) continue // ignore: most likely a single zero byte
  46. if (i === -1) data[b.toString().toLowerCase()] = true
  47. else if (i === 0) continue // ignore: invalid key-length
  48. else {
  49. var key = b.slice(0, i).toString().toLowerCase()
  50. if (key in data) continue // ignore: overwriting not allowed
  51. data[key] = binary ? b.slice(i + 1) : b.slice(i + 1).toString()
  52. }
  53. }
  54. that.decode.bytes = offset - oldOffset
  55. return data
  56. }
  57. that.encodingLength = function (data) {
  58. if (!data) return 1 // 1 byte (single empty byte)
  59. var keys = Object.keys(data)
  60. if (keys.length === 0) return 1 // 1 byte (single empty byte)
  61. return keys.reduce(function (total, key) {
  62. var val = data[key]
  63. total += Buffer.byteLength(key) + 1 // +1 byte to store field length
  64. if (Buffer.isBuffer(val)) total += val.length + 1 // +1 byte to fit equal sign
  65. else if (val !== true) total += Buffer.byteLength(String(val)) + 1 // +1 byte to fit equal sign
  66. return total
  67. }, 0)
  68. }
  69. return that
  70. }
  71. function decodeBlock (buf, offset) {
  72. var len = buf[offset]
  73. var to = offset + 1 + len
  74. var b = buf.slice(offset + 1, to > buf.length ? buf.length : to)
  75. decodeBlock.bytes = len + 1
  76. return b
  77. }