Skip to content

Commit 718c741

Browse files
Update
1 parent f6b7aa0 commit 718c741

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/index/OrderedCodeWriter.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class OrderedCodeWriter {
3333
public static final byte SEPARATOR = 0x01; // Combined with ESCAPE1
3434

3535
public static final byte ESCAPE2 = (byte) 0xff;
36+
public static final byte INFINITY = (byte) 0xff; // Combined with ESCAPE2
3637
public static final byte FF_BYTE = 0x00; // Combined with ESCAPE2
3738

3839
/** These constants are taken from the backend. */
@@ -79,6 +80,13 @@ public void writeBytesAscending(ByteString value) {
7980
writeSeparatorAscending();
8081
}
8182

83+
public void writeBytesDescending(ByteString value) {
84+
for (int i = 0; i < value.size(); ++i) {
85+
writeByteDescending(value.byteAt(i));
86+
}
87+
writeSeparatorDescending();
88+
}
89+
8290
/**
8391
* Writes utf8 bytes into this byte sequence, ascending.
8492
*
@@ -109,6 +117,36 @@ public void writeUtf8Ascending(CharSequence sequence) {
109117
writeSeparatorAscending();
110118
}
111119

120+
/**
121+
* Writes utf8 bytes into this byte sequence, descending.
122+
*
123+
* <p>This is a more efficent version of writeBytesDescending(str.getBytes(UTF_8));
124+
*/
125+
public void writeUtf8Descending(CharSequence sequence) {
126+
int utf16Length = sequence.length();
127+
for (int i = 0; i < utf16Length; i++) {
128+
char c = sequence.charAt(i);
129+
if (c < 0x80) {
130+
writeByteDescending((byte) c);
131+
} else if (c < 0x800) {
132+
writeByteDescending((byte) ((0xF << 6) | (c >>> 6)));
133+
writeByteDescending((byte) (0x80 | (0x3F & c)));
134+
} else if ((c < MIN_SURROGATE || MAX_SURROGATE < c)) {
135+
writeByteDescending((byte) ((0xF << 5) | (c >>> 12)));
136+
writeByteDescending((byte) (0x80 | (0x3F & (c >>> 6))));
137+
writeByteDescending((byte) (0x80 | (0x3F & c)));
138+
} else {
139+
final int codePoint = Character.codePointAt(sequence, i);
140+
++i; // Skip the low surrogate.
141+
writeByteDescending((byte) ((0xF << 4) | (codePoint >>> 18)));
142+
writeByteDescending((byte) (0x80 | (0x3F & (codePoint >>> 12))));
143+
writeByteDescending((byte) (0x80 | (0x3F & (codePoint >>> 6))));
144+
writeByteDescending((byte) (0x80 | (0x3F & codePoint)));
145+
}
146+
}
147+
writeSeparatorDescending();
148+
}
149+
112150
/** Writes an unsigned long in the ordered code format, ascending. */
113151
public void writeUnsignedLongAscending(long value) {
114152
// Values are encoded with a single byte length prefix, followed
@@ -124,6 +162,21 @@ public void writeUnsignedLongAscending(long value) {
124162
position += len;
125163
}
126164

165+
/** Writes an unsigned long in the ordered code format, descending. */
166+
public void writeUnsignedLongDescending(long value) {
167+
// Values are encoded with a complemented single byte length prefix,
168+
// followed by the complement of the actual value in big-endian format with
169+
// leading 0xff bytes dropped.
170+
int len = unsignedNumLength(value);
171+
ensureAvailable(1 + len);
172+
buffer[position++] = (byte) ~len; // Write the length
173+
for (int i = position + len - 1; i >= position; --i) {
174+
buffer[i] = (byte) ~(value & 0xff);
175+
value >>>= 8;
176+
}
177+
position += len;
178+
}
179+
127180
/** Writes a signed long in the ordered code format, ascending. */
128181
public void writeSignedLongAscending(long value) {
129182
long val = value < 0 ? ~value : value;
@@ -162,6 +215,11 @@ public void writeSignedLongAscending(long value) {
162215
position += len;
163216
}
164217

218+
/** Writes a signed long in the ordered code format, descending. */
219+
public void writeSignedLongDescending(long value) {
220+
writeSignedLongAscending(~value);
221+
}
222+
165223
public void writeDoubleAscending(double val) {
166224
// This particular encoding has the following properties:
167225
// The order matches the IEEE 754 floating-point comparison results with the
@@ -174,6 +232,13 @@ public void writeDoubleAscending(double val) {
174232
writeUnsignedLongAscending(v);
175233
}
176234

235+
public void writeDoubleDescending(double val) {
236+
// See note in #writeDoubleAscending
237+
long v = Double.doubleToLongBits(val);
238+
v ^= (v < 0) ? DOUBLE_ALL_BITS : DOUBLE_SIGN_MASK;
239+
writeUnsignedLongDescending(v);
240+
}
241+
177242
/** Resets the buffer such that it is the same as when it was newly constructed. */
178243
public void reset() {
179244
position = 0;
@@ -200,16 +265,42 @@ private void writeByteAscending(byte b) {
200265
}
201266
}
202267

268+
/**
269+
* Writes a single byte descending to the buffer, doing proper escaping as described in {@link
270+
* OrderedCodeConstants}.
271+
*/
272+
private void writeByteDescending(byte b) {
273+
if (b == ESCAPE1) {
274+
writeEscapedByteDescending(ESCAPE1);
275+
writeEscapedByteDescending(NULL_BYTE);
276+
} else if (b == ESCAPE2) {
277+
writeEscapedByteDescending(ESCAPE2);
278+
writeEscapedByteDescending(FF_BYTE);
279+
} else {
280+
writeEscapedByteDescending(b);
281+
}
282+
}
283+
203284
private void writeSeparatorAscending() {
204285
writeEscapedByteAscending(ESCAPE1);
205286
writeEscapedByteAscending(SEPARATOR);
206287
}
207288

289+
private void writeSeparatorDescending() {
290+
writeEscapedByteDescending(ESCAPE1);
291+
writeEscapedByteDescending(SEPARATOR);
292+
}
293+
208294
private void writeEscapedByteAscending(byte b) {
209295
ensureAvailable(1);
210296
buffer[position++] = b;
211297
}
212298

299+
private void writeEscapedByteDescending(byte b) {
300+
ensureAvailable(1);
301+
buffer[position++] = (byte) ~b;
302+
}
303+
213304
private void ensureAvailable(int bytes) {
214305
int minCapacity = bytes + position;
215306
if (minCapacity <= buffer.length) {

0 commit comments

Comments
 (0)