1818
1919import androidx .annotation .NonNull ;
2020import com .google .firebase .firestore .util .Util ;
21+ import java .nio .charset .StandardCharsets ;
2122import java .util .ArrayList ;
2223import java .util .List ;
2324
2728 */
2829public abstract class BasePath <B extends BasePath <B >> implements Comparable <B > {
2930 final List <String > segments ;
31+ List <byte []> utf8Segments = null ;
3032
3133 BasePath (List <String > segments ) {
3234 this .segments = segments ;
@@ -93,8 +95,12 @@ public int compareTo(@NonNull B o) {
9395 int i = 0 ;
9496 int myLength = length ();
9597 int theirLength = o .length ();
98+ List <byte []> myUtf8Segments = ensureUtf8Segments ();
99+ List <byte []> theirUtf8Segments = o .ensureUtf8Segments ();
96100 while (i < myLength && i < theirLength ) {
97- int localCompare = compareSegments (getSegment (i ), o .getSegment (i ));
101+ int localCompare =
102+ compareSegments (
103+ myUtf8Segments .get (i ), theirUtf8Segments .get (i ), getSegment (i ), o .getSegment (i ));
98104 if (localCompare != 0 ) {
99105 return localCompare ;
100106 }
@@ -103,21 +109,39 @@ public int compareTo(@NonNull B o) {
103109 return Integer .compare (myLength , theirLength );
104110 }
105111
106- private static int compareSegments (String lhs , String rhs ) {
107- boolean isLhsNumeric = isNumericId ( lhs ) ;
108- boolean isRhsNumeric = isNumericId ( rhs ) ;
112+ private static int compareSegments (byte [] lhs , byte [] rhs , String lhsString , String rhsString ) {
113+ boolean isLhsNumeric = lhs == null ;
114+ boolean isRhsNumeric = rhs == null ;
109115
110116 if (isLhsNumeric && !isRhsNumeric ) { // Only lhs is numeric
111117 return -1 ;
112118 } else if (!isLhsNumeric && isRhsNumeric ) { // Only rhs is numeric
113119 return 1 ;
114120 } else if (isLhsNumeric && isRhsNumeric ) { // both numeric
115- return Long .compare (extractNumericId (lhs ), extractNumericId (rhs ));
121+ return Long .compare (extractNumericId (lhsString ), extractNumericId (rhsString ));
116122 } else { // both string
117- return Util .compareUtf8Strings (lhs , rhs );
123+ return Util .compareByteArrays (lhs , rhs );
118124 }
119125 }
120126
127+ public List <byte []> ensureUtf8Segments () {
128+ if (this .utf8Segments == null ) {
129+ this .utf8Segments = new ArrayList <>(this .segments .size ());
130+ for (int i = 0 ; i < this .segments .size (); i ++) {
131+ String segment = this .segments .get (i );
132+ boolean isNumeric = isNumericId (segment );
133+ if (!isNumeric ) {
134+ byte [] utf8Bytes = segment .getBytes (StandardCharsets .UTF_8 );
135+ this .utf8Segments .add (utf8Bytes );
136+ } else {
137+ this .utf8Segments .add (null );
138+ }
139+ }
140+ }
141+
142+ return this .utf8Segments ;
143+ }
144+
121145 /** Checks if a segment is a numeric ID (starts with "__id" and ends with "__"). */
122146 private static boolean isNumericId (String segment ) {
123147 return segment .startsWith ("__id" ) && segment .endsWith ("__" );
0 commit comments