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.
		
		
		
		
		
			
		
			
				
					154 lines
				
				4.0 KiB
			
		
		
			
		
	
	
					154 lines
				
				4.0 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const inherits = require('inherits');
							 | 
						||
| 
								 | 
							
								const Reporter = require('../base/reporter').Reporter;
							 | 
						||
| 
								 | 
							
								const Buffer = require('safer-buffer').Buffer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function DecoderBuffer(base, options) {
							 | 
						||
| 
								 | 
							
								  Reporter.call(this, options);
							 | 
						||
| 
								 | 
							
								  if (!Buffer.isBuffer(base)) {
							 | 
						||
| 
								 | 
							
								    this.error('Input not Buffer');
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.base = base;
							 | 
						||
| 
								 | 
							
								  this.offset = 0;
							 | 
						||
| 
								 | 
							
								  this.length = base.length;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								inherits(DecoderBuffer, Reporter);
							 | 
						||
| 
								 | 
							
								exports.DecoderBuffer = DecoderBuffer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.isDecoderBuffer = function isDecoderBuffer(data) {
							 | 
						||
| 
								 | 
							
								  if (data instanceof DecoderBuffer) {
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Or accept compatible API
							 | 
						||
| 
								 | 
							
								  const isCompatible = typeof data === 'object' &&
							 | 
						||
| 
								 | 
							
								    Buffer.isBuffer(data.base) &&
							 | 
						||
| 
								 | 
							
								    data.constructor.name === 'DecoderBuffer' &&
							 | 
						||
| 
								 | 
							
								    typeof data.offset === 'number' &&
							 | 
						||
| 
								 | 
							
								    typeof data.length === 'number' &&
							 | 
						||
| 
								 | 
							
								    typeof data.save === 'function' &&
							 | 
						||
| 
								 | 
							
								    typeof data.restore === 'function' &&
							 | 
						||
| 
								 | 
							
								    typeof data.isEmpty === 'function' &&
							 | 
						||
| 
								 | 
							
								    typeof data.readUInt8 === 'function' &&
							 | 
						||
| 
								 | 
							
								    typeof data.skip === 'function' &&
							 | 
						||
| 
								 | 
							
								    typeof data.raw === 'function';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return isCompatible;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.prototype.save = function save() {
							 | 
						||
| 
								 | 
							
								  return { offset: this.offset, reporter: Reporter.prototype.save.call(this) };
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.prototype.restore = function restore(save) {
							 | 
						||
| 
								 | 
							
								  // Return skipped data
							 | 
						||
| 
								 | 
							
								  const res = new DecoderBuffer(this.base);
							 | 
						||
| 
								 | 
							
								  res.offset = save.offset;
							 | 
						||
| 
								 | 
							
								  res.length = this.offset;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  this.offset = save.offset;
							 | 
						||
| 
								 | 
							
								  Reporter.prototype.restore.call(this, save.reporter);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.prototype.isEmpty = function isEmpty() {
							 | 
						||
| 
								 | 
							
								  return this.offset === this.length;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
							 | 
						||
| 
								 | 
							
								  if (this.offset + 1 <= this.length)
							 | 
						||
| 
								 | 
							
								    return this.base.readUInt8(this.offset++, true);
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    return this.error(fail || 'DecoderBuffer overrun');
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.prototype.skip = function skip(bytes, fail) {
							 | 
						||
| 
								 | 
							
								  if (!(this.offset + bytes <= this.length))
							 | 
						||
| 
								 | 
							
								    return this.error(fail || 'DecoderBuffer overrun');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const res = new DecoderBuffer(this.base);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Share reporter state
							 | 
						||
| 
								 | 
							
								  res._reporterState = this._reporterState;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  res.offset = this.offset;
							 | 
						||
| 
								 | 
							
								  res.length = this.offset + bytes;
							 | 
						||
| 
								 | 
							
								  this.offset += bytes;
							 | 
						||
| 
								 | 
							
								  return res;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								DecoderBuffer.prototype.raw = function raw(save) {
							 | 
						||
| 
								 | 
							
								  return this.base.slice(save ? save.offset : this.offset, this.length);
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function EncoderBuffer(value, reporter) {
							 | 
						||
| 
								 | 
							
								  if (Array.isArray(value)) {
							 | 
						||
| 
								 | 
							
								    this.length = 0;
							 | 
						||
| 
								 | 
							
								    this.value = value.map(function(item) {
							 | 
						||
| 
								 | 
							
								      if (!EncoderBuffer.isEncoderBuffer(item))
							 | 
						||
| 
								 | 
							
								        item = new EncoderBuffer(item, reporter);
							 | 
						||
| 
								 | 
							
								      this.length += item.length;
							 | 
						||
| 
								 | 
							
								      return item;
							 | 
						||
| 
								 | 
							
								    }, this);
							 | 
						||
| 
								 | 
							
								  } else if (typeof value === 'number') {
							 | 
						||
| 
								 | 
							
								    if (!(0 <= value && value <= 0xff))
							 | 
						||
| 
								 | 
							
								      return reporter.error('non-byte EncoderBuffer value');
							 | 
						||
| 
								 | 
							
								    this.value = value;
							 | 
						||
| 
								 | 
							
								    this.length = 1;
							 | 
						||
| 
								 | 
							
								  } else if (typeof value === 'string') {
							 | 
						||
| 
								 | 
							
								    this.value = value;
							 | 
						||
| 
								 | 
							
								    this.length = Buffer.byteLength(value);
							 | 
						||
| 
								 | 
							
								  } else if (Buffer.isBuffer(value)) {
							 | 
						||
| 
								 | 
							
								    this.value = value;
							 | 
						||
| 
								 | 
							
								    this.length = value.length;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    return reporter.error('Unsupported type: ' + typeof value);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.EncoderBuffer = EncoderBuffer;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EncoderBuffer.isEncoderBuffer = function isEncoderBuffer(data) {
							 | 
						||
| 
								 | 
							
								  if (data instanceof EncoderBuffer) {
							 | 
						||
| 
								 | 
							
								    return true;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Or accept compatible API
							 | 
						||
| 
								 | 
							
								  const isCompatible = typeof data === 'object' &&
							 | 
						||
| 
								 | 
							
								    data.constructor.name === 'EncoderBuffer' &&
							 | 
						||
| 
								 | 
							
								    typeof data.length === 'number' &&
							 | 
						||
| 
								 | 
							
								    typeof data.join === 'function';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return isCompatible;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EncoderBuffer.prototype.join = function join(out, offset) {
							 | 
						||
| 
								 | 
							
								  if (!out)
							 | 
						||
| 
								 | 
							
								    out = Buffer.alloc(this.length);
							 | 
						||
| 
								 | 
							
								  if (!offset)
							 | 
						||
| 
								 | 
							
								    offset = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (this.length === 0)
							 | 
						||
| 
								 | 
							
								    return out;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (Array.isArray(this.value)) {
							 | 
						||
| 
								 | 
							
								    this.value.forEach(function(item) {
							 | 
						||
| 
								 | 
							
								      item.join(out, offset);
							 | 
						||
| 
								 | 
							
								      offset += item.length;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    if (typeof this.value === 'number')
							 | 
						||
| 
								 | 
							
								      out[offset] = this.value;
							 | 
						||
| 
								 | 
							
								    else if (typeof this.value === 'string')
							 | 
						||
| 
								 | 
							
								      out.write(this.value, offset);
							 | 
						||
| 
								 | 
							
								    else if (Buffer.isBuffer(this.value))
							 | 
						||
| 
								 | 
							
								      this.value.copy(out, offset);
							 | 
						||
| 
								 | 
							
								    offset += this.length;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return out;
							 | 
						||
| 
								 | 
							
								};
							 |