buffer-to-hex-dump.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. 'use strict'
  2. const { createWriteStream } = require('fs')
  3. /**
  4. * @typedef {object} HexDumpParams
  5. * @property {Buffer} buffer The buffer instance to serialize into a hex dump.
  6. * @property {string} [prefix=''] A string to prefix each byte with, e.g.
  7. * `0x`.
  8. * @property {string} [separator=''] A string to separate each byte with, e.g.
  9. * `, '.
  10. * @property {string[]} [wrapCharacters=[]] A set of characters to wrap the
  11. * output with. For example, `wrapCharacters=['[', ']']` will start the hex
  12. * dump with `[` and end it with `]`.
  13. * @property {number} [width=10] How many bytes to write per line.
  14. * @property {WriteStream | string} [destination=process.stdout] Where to
  15. * write the serialized data. If a string is provided, it is assumed to be
  16. * the path to a file. This file will be completely overwritten.
  17. * @property {boolean} [closeDestination=false] Indicates whether the
  18. * `destination` should be closed when done. This _should_ be `true` when the
  19. * passed in `destination` is a stream that you control. If a string path is
  20. * supplied for the `destination`, this will automatically be handled.
  21. */
  22. // We'd like to put this coverage directive after the doc block,
  23. // but that confuses doc tooling (e.g. WebStorm).
  24. /* istanbul ignore next: defaults don't need 100% coverage */
  25. /**
  26. * Given a buffer of bytes, generate a hex dump that can be loaded later
  27. * or viewed in a hex editor (e.g. [Hex Fiend](https://hexfiend.com)).
  28. *
  29. * @param {HexDumpParams} params
  30. *
  31. * @throws When the destination cannot be accessed.
  32. */
  33. module.exports = function bufferToHexDump ({
  34. buffer,
  35. prefix = '',
  36. separator = '',
  37. wrapCharacters = [],
  38. width = 10,
  39. destination = process.stdout,
  40. closeDestination = false
  41. }) {
  42. let closeStream = closeDestination
  43. if (typeof destination === 'string') {
  44. destination = createWriteStream(destination)
  45. closeStream = true
  46. }
  47. if (wrapCharacters[0]) {
  48. destination.write(wrapCharacters[0])
  49. }
  50. for (const [i, byte] of buffer.entries()) {
  51. const outByte = Number(byte).toString(16).padStart(2, '0')
  52. destination.write(prefix + outByte)
  53. if (i !== buffer.byteLength - 1) {
  54. destination.write(separator)
  55. }
  56. if ((i + 1) % width === 0) {
  57. destination.write('\n')
  58. }
  59. }
  60. if (wrapCharacters[1]) {
  61. destination.write(wrapCharacters[1])
  62. }
  63. /* istanbul ignore else */
  64. if (closeStream === true) {
  65. destination.end()
  66. }
  67. }