Passed
Push — master ( 458687...25f292 )
by Rafael S.
02:11
created

number-buffer.js ➔ setFPReaderAndWriter_   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 1
dl 0
loc 12
rs 9.9
c 0
b 0
f 0
1
/*
2
 * Copyright (c) 2017-2018 Rafael da Silva Rocha.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
/**
26
 * @fileoverview Sserialize and deserialize integers and floats.
27
 * @see https://github.com/rochars/byte-data
28
 */
29
30
import {validateFloatType, validateIntType} from './validation.js';
31
import {unpack, pack} from 'ieee754-buffer';
32
import TwosComplementBuffer from 'twos-complement-buffer';
33
import UintBuffer from 'uint-buffer';
34
35
/**
36
 * A class to pack and unpack integers and floating-point numbers.
37
 * Signed integers are two's complement.
38
 * Floating-point numbers are IEEE 754 standard.
39
 */
40
export default class NumberBuffer {
41
  
42
  constructor(bits, fp, signed) {
43
    if (fp) {
44
      validateFloatType(bits);
45
    } else {
46
      validateIntType(bits);
47
    }
48
    /** @type {TwosComplementBuffer|UintBuffer} */
49
    this.IntBuffer = signed ?
50
      new TwosComplementBuffer(bits) : new UintBuffer(bits);
51
    this.IntBuffer.bytes = this.IntBuffer.bytes === 8 ?
52
      4 : this.IntBuffer.bytes;
53
    if (fp) {
54
      this.setFPReaderAndWriter_(bits);
55
    }
56
  }
57
58
  /**
59
   * Read one number from a byte buffer.
60
   * @param {!Uint8Array|!Array<number>} buffer An array of bytes.
61
   * @param {number=} index The index to read.
62
   * @return {number} The number.
63
   * @throws {Error} On overflow.
64
   */
65
  unpack(buffer, index=0) {
66
    return this.IntBuffer.unpack(buffer, index);
67
  }
68
69
  /**
70
   * Write one number to a byte buffer.
71
   * @param {!Uint8Array|!Array<number>} buffer An array of bytes.
72
   * @param {number} num The number.
73
   * @param {number=} index The index being written in the byte buffer.
74
   * @return {number} The next index to write on the byte buffer.
75
   * @throws {Error} If num is NaN.
76
   * @throws {Error} On overflow.
77
   */
78
  pack(buffer, num, index=0) {
79
    return this.IntBuffer.pack(buffer, num, index);
80
  }
81
82
  /**
83
   * Read one 16-bit float from a byte buffer.
84
   * @see https://stackoverflow.com/a/8796597
85
   * @param {!Uint8Array|!Array<number>} bytes An array of bytes.
86
   * @param {number=} index The index to read.
87
   * @return {number}
88
   * @private
89
   */
90
  read16F_(bytes, index=0) {
91
    return unpack(bytes, index, 5, 11);
92
  }
93
94
  /**
95
   * Read one 32-bit float from a byte buffer.
96
   * @param {!Uint8Array|!Array<number>} bytes An array of bytes.
97
   * @param {number=} index The index to read.
98
   * @return {number}
99
   * @private
100
   */
101
  read32F_(bytes, index=0) {
102
    return unpack(bytes, index, 8, 23);
103
  }
104
105
  /**
106
   * Read one 64-bit float from a byte buffer
107
   * Thanks https://gist.github.com/kg/2192799
108
   * @param {!Uint8Array|!Array<number>} bytes An array of bytes.
109
   * @param {number=} index The index to read.
110
   * @return {number}
111
   * @private
112
   */
113
  read64F_(bytes, index=0) {
114
    return unpack(bytes, index, 11, 52);
115
  }
116
117
  /**
118
   * Write one 16-bit float to a byte buffer.
119
   * @param {!Uint8Array|!Array<number>} bytes An array of bytes.
120
   * @param {number} num The number to write as bytes.
121
   * @param {number=} index The index being written in the byte buffer.
122
   * @return {number} The next index to write on the byte buffer.
123
   * @private
124
   */
125
  write16F_(bytes, num, index=0) {
126
    return pack(bytes, index, num, 5, 11);
127
  }
128
129
  /**
130
   * Write one 32-bit float to a byte buffer.
131
   * @param {!Uint8Array|!Array<number>} bytes An array of bytes.
132
   * @param {number} num The number to write as bytes.
133
   * @param {number=} index The index being written in the byte buffer.
134
   * @return {number} The next index to write on the byte buffer.
135
   * @private
136
   */
137
  write32F_(bytes, num, index=0) {
138
      return pack(bytes, index, num, 8, 23);
139
  }
140
141
  /**
142
   * Write one 64-bit float to a byte buffer.
143
   * @param {!Uint8Array|!Array<number>} bytes An array of bytes.
144
   * @param {number} num The number to write as bytes.
145
   * @param {number=} index The index being written in the byte buffer.
146
   * @return {number} The next index to write on the byte buffer.
147
   * @private
148
   */
149
  write64F_(bytes, num, index=0) {
150
      return pack(bytes, index, num, 11, 52);
151
  }
152
153
  /**
154
   * Set the methods to pack and unpack floating-point numbers.
155
   * @param {number} bits The number of bits.
156
   * @private
157
   */
158
  setFPReaderAndWriter_(bits) {
159
    if (bits === 16) {
160
      this.unpack = this.read16F_;
161
      this.pack = this.write16F_;
162
    } else if(bits === 32) {
163
      this.unpack = this.read32F_;
164
      this.pack = this.write32F_;
165
    } else {
166
      this.unpack = this.read64F_;
167
      this.pack = this.write64F_;
168
    }
169
  }
170
}
171