14
14
* See the License for the specific language governing permissions and
15
15
* limitations under the License.
16
16
*/
17
+ import { debugAssert } from '../util/assert' ;
17
18
18
19
const LONG_SIZE = 64 ;
19
20
const BYTE_SIZE = 8 ;
@@ -25,13 +26,10 @@ const BYTE_SIZE = 8;
25
26
*/
26
27
const DEFAULT_BUFFER_SIZE = 1024 ;
27
28
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). */
32
30
function doubleToLongBits ( value : number ) : Uint8Array {
33
31
const dv = new DataView ( new ArrayBuffer ( 8 ) ) ;
34
- dv . setFloat64 ( 0 , value , false ) ;
32
+ dv . setFloat64 ( 0 , value , /* littleEndian= */ false ) ;
35
33
return new Uint8Array ( dv . buffer ) ;
36
34
}
37
35
@@ -41,6 +39,7 @@ function doubleToLongBits(value: number): Uint8Array {
41
39
* Visible for testing.
42
40
*/
43
41
export function numberOfLeadingZerosInByte ( x : number ) : number {
42
+ debugAssert ( x < 256 , 'Provided value is not a byte: ' + x ) ;
44
43
if ( x === 0 ) {
45
44
return 8 ;
46
45
}
@@ -65,8 +64,12 @@ export function numberOfLeadingZerosInByte(x: number): number {
65
64
66
65
/** Counts the number of leading zeros in the given byte array. */
67
66
function numberOfLeadingZeros ( bytes : Uint8Array ) : number {
67
+ debugAssert (
68
+ bytes . length == 8 ,
69
+ 'Can only count leading zeros in 64-bit numbers'
70
+ ) ;
68
71
let leadingZeros = 0 ;
69
- for ( let i = 0 ; i < bytes . length ; ++ i ) {
72
+ for ( let i = 0 ; i < 8 ; ++ i ) {
70
73
const zeros = numberOfLeadingZerosInByte ( bytes [ i ] & 0xff ) ;
71
74
leadingZeros += zeros ;
72
75
if ( zeros !== 8 ) {
@@ -97,6 +100,8 @@ export class OrderedCodeWriter {
97
100
position = 0 ;
98
101
99
102
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.
100
105
const value = this . toOrderedBits ( val ) ;
101
106
const len = unsignedNumLength ( value ) ;
102
107
this . ensureAvailable ( 1 + len ) ;
@@ -107,6 +112,8 @@ export class OrderedCodeWriter {
107
112
}
108
113
109
114
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.
110
117
const value = this . toOrderedBits ( val ) ;
111
118
const len = unsignedNumLength ( value ) ;
112
119
this . ensureAvailable ( 1 + len ) ;
@@ -125,7 +132,11 @@ export class OrderedCodeWriter {
125
132
*/
126
133
private toOrderedBits ( val : number ) : Uint8Array {
127
134
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.
128
137
const isNegative = ( value [ 0 ] & 0x80 ) !== 0 ;
138
+
139
+ // Revert the two complement to get natural ordering
129
140
value [ 0 ] ^= isNegative ? 0xff : 0x80 ;
130
141
for ( let i = 1 ; i < value . length ; ++ i ) {
131
142
value [ i ] ^= isNegative ? 0xff : 0x00 ;
0 commit comments