# 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

    1412x

    1412x

    13438x
    13438x

    5779x
    5779x
    5779x
    5779x

    857x
    857x
    857x
    857x

    6x
    6x
    6x
    6x

    6796x
    6796x

    13438x
    13438x

    13438x

    65x
    65x
    65x
    13832x
    7561x

    6512x
    6512x

    65x

    1760x
    1301x
    1301x

    1760x

     // @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;
      }
    }