All files / src/utils output-stream.js

100% Statements 37/37
100% Branches 12/12
100% Functions 6/6
100% Lines 36/36
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82  23x 23x 23x                 1576x     1576x       14230x 14230x           6297x 6297x 6297x 6297x     844x 844x 844x 844x     22x 22x 22x 22x     7067x 7067x       14230x 14230x   14230x           72x 72x 72x 14622x 8113x   6779x 6779x     72x         1951x 1453x 1453x     1951x      
// @flow
import invariant from 'invariant';
import { encodeSigned, encodeUnsigned } from './leb128';
import { sizeof, set, u8 } from 'wasm-types';
 
// Used to output raw binary, holds values and types in a large array 'stream'
export default class OutputStream {
  data: Array<any>;
  size: number;
 
  constructor() {
    // Our data, expand it
    this.data = [];
 
    // start at the beginning
    this.size = 0;
  }
 
  push(type: string, value: any, debug: string) {
    let size = 0;
    switch (type) {
      case 'varuint7':
      case 'varuint32':
      case 'varint7':
      case 'varint1': {
        // Encode all of the LEB128 aka 'var*' types
        value = encodeUnsigned(value);
        size = value.length;
        invariant(size, `Cannot write a value of size ${size}`);
        break;
      }
      case 'varint32': {
        value = encodeSigned(value);
        size = value.length;
        invariant(size, `Cannot write a value of size ${size}`);
        break;
      }
      case 'varint64': {
        value = encodeSigned(value);
        size = value.length;
        invariant(size, `Cannot write a value of size ${size}`);
        break;
      }
      default: {
        size = sizeof[type];
        invariant(size, `Cannot write a value of size ${size}, type ${type}`);
      }
    }
 
    this.data.push({ type, value, debug });
    this.size += size;
 
    return this;
  }
 
  // Get the BUFFER, not data array.
  // Returns a new buffer unless one is passed in to be written to.
  buffer(buffer: ArrayBuffer = new ArrayBuffer(this.size)) {
    const view = new DataView(buffer);
    let pc = 0;
    this.data.forEach(({ type, value }) => {
      if (Array.isArray(value)) {
        value.forEach(v => set(u8, pc++, view, v));
      } else {
        set(type, pc, view, value);
        pc += sizeof[type];
      }
    });
    return buffer;
  }
 
  // Writes source OutputStream into the current buffer
  write(source: ?OutputStream) {
    if (source) {
      this.data = this.data.concat(source.data);
      this.size += source.size;
    }
 
    return this;
  }
}