1'use strict';
2
3require('../common');
4const assert = require('assert');
5
6// We need to check the following things:
7//  - We are correctly resolving big endian (doesn't mean anything for 8 bit)
8//  - Correctly resolving little endian (doesn't mean anything for 8 bit)
9//  - Correctly using the offsets
10//  - Correctly interpreting values that are beyond the signed range as unsigned
11
12{ // OOB
13  const data = Buffer.alloc(8);
14  ['UInt8', 'UInt16BE', 'UInt16LE', 'UInt32BE', 'UInt32LE'].forEach((fn) => {
15
16    // Verify that default offset works fine.
17    data[`write${fn}`](23, undefined);
18    data[`write${fn}`](23);
19
20    ['', '0', null, {}, [], () => {}, true, false].forEach((o) => {
21      assert.throws(
22        () => data[`write${fn}`](23, o),
23        { code: 'ERR_INVALID_ARG_TYPE' });
24    });
25
26    [NaN, Infinity, -1, 1.01].forEach((o) => {
27      assert.throws(
28        () => data[`write${fn}`](23, o),
29        { code: 'ERR_OUT_OF_RANGE' });
30    });
31  });
32}
33
34{ // Test 8 bit
35  const data = Buffer.alloc(4);
36
37  data.writeUInt8(23, 0);
38  data.writeUInt8(23, 1);
39  data.writeUInt8(23, 2);
40  data.writeUInt8(23, 3);
41  assert.ok(data.equals(new Uint8Array([23, 23, 23, 23])));
42
43  data.writeUInt8(23, 0);
44  data.writeUInt8(23, 1);
45  data.writeUInt8(23, 2);
46  data.writeUInt8(23, 3);
47  assert.ok(data.equals(new Uint8Array([23, 23, 23, 23])));
48
49  data.writeUInt8(255, 0);
50  assert.strictEqual(data[0], 255);
51
52  data.writeUInt8(255, 0);
53  assert.strictEqual(data[0], 255);
54}
55
56// Test 16 bit
57{
58  let value = 0x2343;
59  const data = Buffer.alloc(4);
60
61  data.writeUInt16BE(value, 0);
62  assert.ok(data.equals(new Uint8Array([0x23, 0x43, 0, 0])));
63
64  data.writeUInt16BE(value, 1);
65  assert.ok(data.equals(new Uint8Array([0x23, 0x23, 0x43, 0])));
66
67  data.writeUInt16BE(value, 2);
68  assert.ok(data.equals(new Uint8Array([0x23, 0x23, 0x23, 0x43])));
69
70  data.writeUInt16LE(value, 0);
71  assert.ok(data.equals(new Uint8Array([0x43, 0x23, 0x23, 0x43])));
72
73  data.writeUInt16LE(value, 1);
74  assert.ok(data.equals(new Uint8Array([0x43, 0x43, 0x23, 0x43])));
75
76  data.writeUInt16LE(value, 2);
77  assert.ok(data.equals(new Uint8Array([0x43, 0x43, 0x43, 0x23])));
78
79  value = 0xff80;
80  data.writeUInt16LE(value, 0);
81  assert.ok(data.equals(new Uint8Array([0x80, 0xff, 0x43, 0x23])));
82
83  data.writeUInt16BE(value, 0);
84  assert.ok(data.equals(new Uint8Array([0xff, 0x80, 0x43, 0x23])));
85
86  value = 0xfffff;
87  ['writeUInt16BE', 'writeUInt16LE'].forEach((fn) => {
88    assert.throws(
89      () => data[fn](value, 0),
90      {
91        code: 'ERR_OUT_OF_RANGE',
92        message: 'The value of "value" is out of range. ' +
93                 `It must be >= 0 and <= 65535. Received ${value}`
94      }
95    );
96  });
97}
98
99// Test 32 bit
100{
101  const data = Buffer.alloc(6);
102  const value = 0xe7f90a6d;
103
104  data.writeUInt32BE(value, 0);
105  assert.ok(data.equals(new Uint8Array([0xe7, 0xf9, 0x0a, 0x6d, 0, 0])));
106
107  data.writeUInt32BE(value, 1);
108  assert.ok(data.equals(new Uint8Array([0xe7, 0xe7, 0xf9, 0x0a, 0x6d, 0])));
109
110  data.writeUInt32BE(value, 2);
111  assert.ok(data.equals(new Uint8Array([0xe7, 0xe7, 0xe7, 0xf9, 0x0a, 0x6d])));
112
113  data.writeUInt32LE(value, 0);
114  assert.ok(data.equals(new Uint8Array([0x6d, 0x0a, 0xf9, 0xe7, 0x0a, 0x6d])));
115
116  data.writeUInt32LE(value, 1);
117  assert.ok(data.equals(new Uint8Array([0x6d, 0x6d, 0x0a, 0xf9, 0xe7, 0x6d])));
118
119  data.writeUInt32LE(value, 2);
120  assert.ok(data.equals(new Uint8Array([0x6d, 0x6d, 0x6d, 0x0a, 0xf9, 0xe7])));
121}
122
123// Test 48 bit
124{
125  const value = 0x1234567890ab;
126  const data = Buffer.allocUnsafe(6);
127  data.writeUIntBE(value, 0, 6);
128  assert.ok(data.equals(new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xab])));
129
130  data.writeUIntLE(value, 0, 6);
131  assert.ok(data.equals(new Uint8Array([0xab, 0x90, 0x78, 0x56, 0x34, 0x12])));
132}
133
134// Test UInt
135{
136  const data = Buffer.alloc(8);
137  let val = 0x100;
138
139  // Check byteLength.
140  ['writeUIntBE', 'writeUIntLE'].forEach((fn) => {
141    ['', '0', null, {}, [], () => {}, true, false, undefined].forEach((bl) => {
142      assert.throws(
143        () => data[fn](23, 0, bl),
144        { code: 'ERR_INVALID_ARG_TYPE' });
145    });
146
147    [Infinity, -1].forEach((byteLength) => {
148      assert.throws(
149        () => data[fn](23, 0, byteLength),
150        {
151          code: 'ERR_OUT_OF_RANGE',
152          message: 'The value of "byteLength" is out of range. ' +
153                   `It must be >= 1 and <= 6. Received ${byteLength}`
154        }
155      );
156    });
157
158    [NaN, 1.01].forEach((byteLength) => {
159      assert.throws(
160        () => data[fn](42, 0, byteLength),
161        {
162          code: 'ERR_OUT_OF_RANGE',
163          name: 'RangeError',
164          message: 'The value of "byteLength" is out of range. ' +
165                   `It must be an integer. Received ${byteLength}`
166        });
167    });
168  });
169
170  // Test 1 to 6 bytes.
171  for (let i = 1; i <= 6; i++) {
172    const range = i < 5 ? `= ${val - 1}` : ` 2 ** ${i * 8}`;
173    const received = i > 4 ?
174      String(val).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1_') :
175      val;
176    ['writeUIntBE', 'writeUIntLE'].forEach((fn) => {
177      assert.throws(() => {
178        data[fn](val, 0, i);
179      }, {
180        code: 'ERR_OUT_OF_RANGE',
181        name: 'RangeError',
182        message: 'The value of "value" is out of range. ' +
183                 `It must be >= 0 and <${range}. Received ${received}`
184      });
185
186      ['', '0', null, {}, [], () => {}, true, false].forEach((o) => {
187        assert.throws(
188          () => data[fn](23, o, i),
189          {
190            code: 'ERR_INVALID_ARG_TYPE',
191            name: 'TypeError'
192          });
193      });
194
195      [Infinity, -1, -4294967295].forEach((offset) => {
196        assert.throws(
197          () => data[fn](val - 1, offset, i),
198          {
199            code: 'ERR_OUT_OF_RANGE',
200            name: 'RangeError',
201            message: 'The value of "offset" is out of range. ' +
202                     `It must be >= 0 and <= ${8 - i}. Received ${offset}`
203          });
204      });
205
206      [NaN, 1.01].forEach((offset) => {
207        assert.throws(
208          () => data[fn](val - 1, offset, i),
209          {
210            code: 'ERR_OUT_OF_RANGE',
211            name: 'RangeError',
212            message: 'The value of "offset" is out of range. ' +
213                     `It must be an integer. Received ${offset}`
214          });
215      });
216    });
217
218    val *= 0x100;
219  }
220}
221
222for (const fn of [
223  'UInt8', 'UInt16LE', 'UInt16BE', 'UInt32LE', 'UInt32BE', 'UIntLE', 'UIntBE',
224  'BigUInt64LE', 'BigUInt64BE',
225]) {
226  const p = Buffer.prototype;
227  const lowerFn = fn.replace(/UInt/, 'Uint');
228  assert.strictEqual(p[`write${fn}`], p[`write${lowerFn}`]);
229  assert.strictEqual(p[`read${fn}`], p[`read${lowerFn}`]);
230}
231