index.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /**
  2. * Module dependencies.
  3. */
  4. var fmt = require('util').format;
  5. var amp = require('amp');
  6. /**
  7. * Proxy methods.
  8. */
  9. var methods = [
  10. 'push',
  11. 'pop',
  12. 'shift',
  13. 'unshift'
  14. ];
  15. /**
  16. * Expose `Message`.
  17. */
  18. module.exports = Message;
  19. /**
  20. * Initialize an AMP message with the
  21. * given `args` or message buffer.
  22. *
  23. * @param {Array|Buffer} args or blob
  24. * @api public
  25. */
  26. function Message(args) {
  27. if (Buffer.isBuffer(args)) args = decode(args);
  28. this.args = args || [];
  29. }
  30. // proxy methods
  31. methods.forEach(function(method){
  32. Message.prototype[method] = function(){
  33. return this.args[method].apply(this.args, arguments);
  34. };
  35. });
  36. /**
  37. * Inspect the message.
  38. *
  39. * @return {String}
  40. * @api public
  41. */
  42. Message.prototype.inspect = function(){
  43. return fmt('<Message args=%d size=%d>',
  44. this.args.length,
  45. this.toBuffer().length);
  46. };
  47. /**
  48. * Return an encoded AMP message.
  49. *
  50. * @return {Buffer}
  51. * @api public
  52. */
  53. Message.prototype.toBuffer = function(){
  54. return encode(this.args);
  55. };
  56. /**
  57. * Decode `msg` and unpack all args.
  58. *
  59. * @param {Buffer} msg
  60. * @return {Array}
  61. * @api private
  62. */
  63. function decode(msg) {
  64. var args = amp.decode(msg);
  65. for (var i = 0; i < args.length; i++) {
  66. args[i] = unpack(args[i]);
  67. }
  68. return args;
  69. }
  70. /**
  71. * Encode and pack all `args`.
  72. *
  73. * @param {Array} args
  74. * @return {Buffer}
  75. * @api private
  76. */
  77. function encode(args) {
  78. var tmp = new Array(args.length);
  79. for (var i = 0; i < args.length; i++) {
  80. tmp[i] = pack(args[i]);
  81. }
  82. return amp.encode(tmp);
  83. }
  84. /**
  85. * Pack `arg`.
  86. *
  87. * @param {Mixed} arg
  88. * @return {Buffer}
  89. * @api private
  90. */
  91. function pack(arg) {
  92. // blob
  93. if (Buffer.isBuffer(arg)) return arg;
  94. // string
  95. if ('string' == typeof arg) return new Buffer('s:' + arg);
  96. // undefined
  97. if (arg === undefined) arg = null;
  98. // json
  99. return new Buffer('j:' + JSON.stringify(arg));
  100. }
  101. /**
  102. * Unpack `arg`.
  103. *
  104. * @param {Buffer} arg
  105. * @return {Mixed}
  106. * @api private
  107. */
  108. function unpack(arg) {
  109. // json
  110. if (isJSON(arg)) return JSON.parse(arg.slice(2));
  111. // string
  112. if (isString(arg)) return arg.slice(2).toString();
  113. // blob
  114. return arg;
  115. }
  116. /**
  117. * String argument.
  118. */
  119. function isString(arg) {
  120. return 115 == arg[0] && 58 == arg[1];
  121. }
  122. /**
  123. * JSON argument.
  124. */
  125. function isJSON(arg) {
  126. return 106 == arg[0] && 58 == arg[1];
  127. }
  128. /**
  129. * ID argument.
  130. */
  131. function isId(arg) {
  132. return 105 == arg[0] && 58 == arg[1];
  133. }