Skip to content

Commit 92a8b8e

Browse files
Comments
1 parent ba2e33a commit 92a8b8e

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

packages/firestore/src/index/ordered_code_writer.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17+
import { debugAssert } from '../util/assert';
1718

1819
const LONG_SIZE = 64;
1920
const BYTE_SIZE = 8;
@@ -25,13 +26,10 @@ const BYTE_SIZE = 8;
2526
*/
2627
const DEFAULT_BUFFER_SIZE = 1024;
2728

28-
/**
29-
* Converts a JavaScript number to a byte array (using little endian
30-
* encoding).
31-
*/
29+
/** Converts a JavaScript number to a byte array (using big endian encoding). */
3230
function doubleToLongBits(value: number): Uint8Array {
3331
const dv = new DataView(new ArrayBuffer(8));
34-
dv.setFloat64(0, value, false);
32+
dv.setFloat64(0, value, /* littleEndian= */ false);
3533
return new Uint8Array(dv.buffer);
3634
}
3735

@@ -41,6 +39,7 @@ function doubleToLongBits(value: number): Uint8Array {
4139
* Visible for testing.
4240
*/
4341
export function numberOfLeadingZerosInByte(x: number): number {
42+
debugAssert(x < 256, 'Provided value is not a byte: ' + x);
4443
if (x === 0) {
4544
return 8;
4645
}
@@ -65,8 +64,12 @@ export function numberOfLeadingZerosInByte(x: number): number {
6564

6665
/** Counts the number of leading zeros in the given byte array. */
6766
function numberOfLeadingZeros(bytes: Uint8Array): number {
67+
debugAssert(
68+
bytes.length == 8,
69+
'Can only count leading zeros in 64-bit numbers'
70+
);
6871
let leadingZeros = 0;
69-
for (let i = 0; i < bytes.length; ++i) {
72+
for (let i = 0; i < 8; ++i) {
7073
const zeros = numberOfLeadingZerosInByte(bytes[i] & 0xff);
7174
leadingZeros += zeros;
7275
if (zeros !== 8) {
@@ -97,6 +100,8 @@ export class OrderedCodeWriter {
97100
position = 0;
98101

99102
writeNumberAscending(val: number): void {
103+
// Values are encoded with a single byte length prefix, followed by the
104+
// actual value in big-endian format with leading 0 bytes dropped.
100105
const value = this.toOrderedBits(val);
101106
const len = unsignedNumLength(value);
102107
this.ensureAvailable(1 + len);
@@ -107,6 +112,8 @@ export class OrderedCodeWriter {
107112
}
108113

109114
writeNumberDescending(val: number): void {
115+
// Values are encoded with a single byte length prefix, followed by the
116+
// inverted value in big-endian format with leading 0 bytes dropped.
110117
const value = this.toOrderedBits(val);
111118
const len = unsignedNumLength(value);
112119
this.ensureAvailable(1 + len);
@@ -125,7 +132,11 @@ export class OrderedCodeWriter {
125132
*/
126133
private toOrderedBits(val: number): Uint8Array {
127134
const value = doubleToLongBits(val);
135+
// Check if the first bit is set. We use a bit mask since value[0] is
136+
// encoded as a number from 0 to 255.
128137
const isNegative = (value[0] & 0x80) !== 0;
138+
139+
// Revert the two complement to get natural ordering
129140
value[0] ^= isNegative ? 0xff : 0x80;
130141
for (let i = 1; i < value.length; ++i) {
131142
value[i] ^= isNegative ? 0xff : 0x00;

0 commit comments

Comments
 (0)