@@ -160,7 +160,7 @@ export const MIN_BSON_BINARY_VALUE: Value = {
160
160
}
161
161
} ;
162
162
163
- export enum SpecialMapValueType {
163
+ export enum MapRepresentation {
164
164
REGEX = 'regexValue' ,
165
165
BSON_OBJECT_ID = 'bsonObjectIdValue' ,
166
166
INT32 = 'int32Value' ,
@@ -195,27 +195,27 @@ export function typeOrder(value: Value): TypeOrder {
195
195
} else if ( 'arrayValue' in value ) {
196
196
return TypeOrder . ArrayValue ;
197
197
} else if ( 'mapValue' in value ) {
198
- const valueType = detectSpecialMapType ( value ) ;
198
+ const valueType = detectMapRepresentation ( value ) ;
199
199
switch ( valueType ) {
200
- case SpecialMapValueType . SERVER_TIMESTAMP :
200
+ case MapRepresentation . SERVER_TIMESTAMP :
201
201
return TypeOrder . ServerTimestampValue ;
202
- case SpecialMapValueType . INTERNAL_MAX :
202
+ case MapRepresentation . INTERNAL_MAX :
203
203
return TypeOrder . MaxValue ;
204
- case SpecialMapValueType . VECTOR :
204
+ case MapRepresentation . VECTOR :
205
205
return TypeOrder . VectorValue ;
206
- case SpecialMapValueType . REGEX :
206
+ case MapRepresentation . REGEX :
207
207
return TypeOrder . RegexValue ;
208
- case SpecialMapValueType . BSON_OBJECT_ID :
208
+ case MapRepresentation . BSON_OBJECT_ID :
209
209
return TypeOrder . BsonObjectIdValue ;
210
- case SpecialMapValueType . INT32 :
210
+ case MapRepresentation . INT32 :
211
211
return TypeOrder . NumberValue ;
212
- case SpecialMapValueType . BSON_TIMESTAMP :
212
+ case MapRepresentation . BSON_TIMESTAMP :
213
213
return TypeOrder . BsonTimestampValue ;
214
- case SpecialMapValueType . BSON_BINARY :
214
+ case MapRepresentation . BSON_BINARY :
215
215
return TypeOrder . BsonBinaryValue ;
216
- case SpecialMapValueType . MIN_KEY :
216
+ case MapRepresentation . MIN_KEY :
217
217
return TypeOrder . MinKeyValue ;
218
- case SpecialMapValueType . MAX_KEY :
218
+ case MapRepresentation . MAX_KEY :
219
219
return TypeOrder . MaxKeyValue ;
220
220
default :
221
221
return TypeOrder . ObjectValue ;
@@ -319,8 +319,8 @@ function blobEquals(left: Value, right: Value): boolean {
319
319
export function numberEquals ( left : Value , right : Value ) : boolean {
320
320
if (
321
321
( 'integerValue' in left && 'integerValue' in right ) ||
322
- ( detectSpecialMapType ( left ) === SpecialMapValueType . INT32 &&
323
- detectSpecialMapType ( right ) === SpecialMapValueType . INT32 )
322
+ ( detectMapRepresentation ( left ) === MapRepresentation . INT32 &&
323
+ detectMapRepresentation ( right ) === MapRepresentation . INT32 )
324
324
) {
325
325
return extractNumber ( left ) === extractNumber ( right ) ;
326
326
} else if ( 'doubleValue' in left && 'doubleValue' in right ) {
@@ -427,7 +427,7 @@ export function valueCompare(left: Value, right: Value): number {
427
427
428
428
export function extractNumber ( value : Value ) : number {
429
429
let numberValue ;
430
- if ( detectSpecialMapType ( value ) === SpecialMapValueType . INT32 ) {
430
+ if ( detectMapRepresentation ( value ) === MapRepresentation . INT32 ) {
431
431
numberValue = value . mapValue ! . fields ! [ RESERVED_INT32_KEY ] . integerValue ! ;
432
432
} else {
433
433
numberValue = value . integerValue || value . doubleValue ;
@@ -686,10 +686,6 @@ function canonifyValue(value: Value): string {
686
686
} else if ( 'arrayValue' in value ) {
687
687
return canonifyArray ( value . arrayValue ! ) ;
688
688
} else if ( 'mapValue' in value ) {
689
- // BsonBinaryValue contains an array of bytes, and needs to extract `subtype` and `data` from it before canonifying.
690
- if ( detectSpecialMapType ( value ) === SpecialMapValueType . BSON_BINARY ) {
691
- return canonifyBsonBinaryData ( value . mapValue ! ) ;
692
- }
693
689
return canonifyMap ( value . mapValue ! ) ;
694
690
} else {
695
691
return fail ( 'Invalid value type: ' + JSON . stringify ( value ) ) ;
@@ -713,19 +709,6 @@ function canonifyReference(referenceValue: string): string {
713
709
return DocumentKey . fromName ( referenceValue ) . toString ( ) ;
714
710
}
715
711
716
- function canonifyBsonBinaryData ( mapValue : MapValue ) : string {
717
- const fields = mapValue ! . fields ?. [ RESERVED_BSON_BINARY_KEY ] ;
718
- const subtypeAndData = fields ?. bytesValue ;
719
- if ( ! subtypeAndData ) {
720
- throw new Error ( 'Received incorrect bytesValue for BsonBinaryData' ) ;
721
- }
722
- // Normalize the bytesValue to Uint8Array before extracting subtype and data.
723
- const bytes = normalizeByteString ( subtypeAndData ) . toUint8Array ( ) ;
724
- return `{__binary__:{subType:${ bytes . at ( 0 ) } ,data:${ canonifyByteString (
725
- bytes . slice ( 1 )
726
- ) } }}`;
727
- }
728
-
729
712
function canonifyMap ( mapValue : MapValue ) : string {
730
713
// Iteration order in JavaScript is not guaranteed. To ensure that we generate
731
714
// matching canonical IDs for identical maps, we need to sort the keys.
@@ -886,35 +869,41 @@ export function isMapValue(
886
869
return ! ! value && 'mapValue' in value ;
887
870
}
888
871
889
- export function detectSpecialMapType ( value : Value ) : SpecialMapValueType {
872
+ export function detectMapRepresentation ( value : Value ) : MapRepresentation {
890
873
if ( ! value || ! value . mapValue || ! value . mapValue . fields ) {
891
- return SpecialMapValueType . REGULAR_MAP ; // Not a special map type
874
+ return MapRepresentation . REGULAR_MAP ; // Not a special map type
892
875
}
893
876
894
877
const fields = value . mapValue . fields ;
895
878
896
879
// Check for type-based mappings
897
880
const type = fields [ TYPE_KEY ] ?. stringValue ;
898
881
if ( type ) {
899
- const typeMap : Record < string , SpecialMapValueType > = {
900
- [ RESERVED_VECTOR_KEY ] : SpecialMapValueType . VECTOR ,
901
- [ RESERVED_MAX_KEY ] : SpecialMapValueType . INTERNAL_MAX ,
902
- [ RESERVED_SERVER_TIMESTAMP_KEY ] : SpecialMapValueType . SERVER_TIMESTAMP
882
+ const typeMap : Record < string , MapRepresentation > = {
883
+ [ RESERVED_VECTOR_KEY ] : MapRepresentation . VECTOR ,
884
+ [ RESERVED_MAX_KEY ] : MapRepresentation . INTERNAL_MAX ,
885
+ [ RESERVED_SERVER_TIMESTAMP_KEY ] : MapRepresentation . SERVER_TIMESTAMP
903
886
} ;
904
887
if ( typeMap [ type ] ) {
905
888
return typeMap [ type ] ;
906
889
}
907
890
}
908
891
892
+ if ( objectSize ( fields ) !== 1 ) {
893
+ // All BSON types have 1 key in the map. To improve performance, we can
894
+ // return early if the number of keys in the map is not 1.
895
+ return MapRepresentation . REGULAR_MAP ;
896
+ }
897
+
909
898
// Check for BSON-related mappings
910
- const bsonMap : Record < string , SpecialMapValueType > = {
911
- [ RESERVED_REGEX_KEY ] : SpecialMapValueType . REGEX ,
912
- [ RESERVED_BSON_OBJECT_ID_KEY ] : SpecialMapValueType . BSON_OBJECT_ID ,
913
- [ RESERVED_INT32_KEY ] : SpecialMapValueType . INT32 ,
914
- [ RESERVED_BSON_TIMESTAMP_KEY ] : SpecialMapValueType . BSON_TIMESTAMP ,
915
- [ RESERVED_BSON_BINARY_KEY ] : SpecialMapValueType . BSON_BINARY ,
916
- [ RESERVED_MIN_KEY ] : SpecialMapValueType . MIN_KEY ,
917
- [ RESERVED_MAX_KEY ] : SpecialMapValueType . MAX_KEY
899
+ const bsonMap : Record < string , MapRepresentation > = {
900
+ [ RESERVED_REGEX_KEY ] : MapRepresentation . REGEX ,
901
+ [ RESERVED_BSON_OBJECT_ID_KEY ] : MapRepresentation . BSON_OBJECT_ID ,
902
+ [ RESERVED_INT32_KEY ] : MapRepresentation . INT32 ,
903
+ [ RESERVED_BSON_TIMESTAMP_KEY ] : MapRepresentation . BSON_TIMESTAMP ,
904
+ [ RESERVED_BSON_BINARY_KEY ] : MapRepresentation . BSON_BINARY ,
905
+ [ RESERVED_MIN_KEY ] : MapRepresentation . MIN_KEY ,
906
+ [ RESERVED_MAX_KEY ] : MapRepresentation . MAX_KEY
918
907
} ;
919
908
920
909
for ( const key in bsonMap ) {
@@ -923,20 +912,20 @@ export function detectSpecialMapType(value: Value): SpecialMapValueType {
923
912
}
924
913
}
925
914
926
- return SpecialMapValueType . REGULAR_MAP ;
915
+ return MapRepresentation . REGULAR_MAP ;
927
916
}
928
917
929
918
export function isBsonType ( value : Value ) : boolean {
930
919
const bsonTypes = new Set ( [
931
- SpecialMapValueType . REGEX ,
932
- SpecialMapValueType . BSON_OBJECT_ID ,
933
- SpecialMapValueType . INT32 ,
934
- SpecialMapValueType . BSON_TIMESTAMP ,
935
- SpecialMapValueType . BSON_BINARY ,
936
- SpecialMapValueType . MIN_KEY ,
937
- SpecialMapValueType . MAX_KEY
920
+ MapRepresentation . REGEX ,
921
+ MapRepresentation . BSON_OBJECT_ID ,
922
+ MapRepresentation . INT32 ,
923
+ MapRepresentation . BSON_TIMESTAMP ,
924
+ MapRepresentation . BSON_BINARY ,
925
+ MapRepresentation . MIN_KEY ,
926
+ MapRepresentation . MAX_KEY
938
927
] ) ;
939
- return bsonTypes . has ( detectSpecialMapType ( value ) ) ;
928
+ return bsonTypes . has ( detectMapRepresentation ( value ) ) ;
940
929
}
941
930
942
931
/** Creates a deep copy of `source`. */
@@ -987,23 +976,23 @@ export function valuesGetLowerBound(value: Value): Value {
987
976
} else if ( 'arrayValue' in value ) {
988
977
return { arrayValue : { } } ;
989
978
} else if ( 'mapValue' in value ) {
990
- const type = detectSpecialMapType ( value ) ;
991
- if ( type === SpecialMapValueType . VECTOR ) {
979
+ const type = detectMapRepresentation ( value ) ;
980
+ if ( type === MapRepresentation . VECTOR ) {
992
981
return MIN_VECTOR_VALUE ;
993
- } else if ( type === SpecialMapValueType . BSON_OBJECT_ID ) {
982
+ } else if ( type === MapRepresentation . BSON_OBJECT_ID ) {
994
983
return MIN_BSON_OBJECT_ID_VALUE ;
995
- } else if ( type === SpecialMapValueType . BSON_TIMESTAMP ) {
984
+ } else if ( type === MapRepresentation . BSON_TIMESTAMP ) {
996
985
return MIN_BSON_TIMESTAMP_VALUE ;
997
- } else if ( type === SpecialMapValueType . BSON_BINARY ) {
986
+ } else if ( type === MapRepresentation . BSON_BINARY ) {
998
987
return MIN_BSON_BINARY_VALUE ;
999
- } else if ( type === SpecialMapValueType . REGEX ) {
988
+ } else if ( type === MapRepresentation . REGEX ) {
1000
989
return MIN_REGEX_VALUE ;
1001
- } else if ( type === SpecialMapValueType . INT32 ) {
990
+ } else if ( type === MapRepresentation . INT32 ) {
1002
991
// int32Value is treated the same as integerValue and doubleValue
1003
992
return { doubleValue : NaN } ;
1004
- } else if ( type === SpecialMapValueType . MIN_KEY ) {
993
+ } else if ( type === MapRepresentation . MIN_KEY ) {
1005
994
return MIN_KEY_VALUE ;
1006
- } else if ( type === SpecialMapValueType . MAX_KEY ) {
995
+ } else if ( type === MapRepresentation . MAX_KEY ) {
1007
996
return MAX_KEY_VALUE ;
1008
997
}
1009
998
return { mapValue : { } } ;
@@ -1033,23 +1022,23 @@ export function valuesGetUpperBound(value: Value): Value {
1033
1022
} else if ( 'arrayValue' in value ) {
1034
1023
return MIN_VECTOR_VALUE ;
1035
1024
} else if ( 'mapValue' in value ) {
1036
- const type = detectSpecialMapType ( value ) ;
1037
- if ( type === SpecialMapValueType . VECTOR ) {
1025
+ const type = detectMapRepresentation ( value ) ;
1026
+ if ( type === MapRepresentation . VECTOR ) {
1038
1027
return { mapValue : { } } ;
1039
- } else if ( type === SpecialMapValueType . BSON_OBJECT_ID ) {
1028
+ } else if ( type === MapRepresentation . BSON_OBJECT_ID ) {
1040
1029
return { geoPointValue : { latitude : - 90 , longitude : - 180 } } ;
1041
- } else if ( type === SpecialMapValueType . BSON_TIMESTAMP ) {
1030
+ } else if ( type === MapRepresentation . BSON_TIMESTAMP ) {
1042
1031
return { stringValue : '' } ;
1043
- } else if ( type === SpecialMapValueType . BSON_BINARY ) {
1032
+ } else if ( type === MapRepresentation . BSON_BINARY ) {
1044
1033
return refValue ( DatabaseId . empty ( ) , DocumentKey . empty ( ) ) ;
1045
- } else if ( type === SpecialMapValueType . REGEX ) {
1034
+ } else if ( type === MapRepresentation . REGEX ) {
1046
1035
return { arrayValue : { } } ;
1047
- } else if ( type === SpecialMapValueType . INT32 ) {
1036
+ } else if ( type === MapRepresentation . INT32 ) {
1048
1037
// int32Value is treated the same as integerValue and doubleValue
1049
1038
return { timestampValue : { seconds : Number . MIN_SAFE_INTEGER } } ;
1050
- } else if ( type === SpecialMapValueType . MIN_KEY ) {
1039
+ } else if ( type === MapRepresentation . MIN_KEY ) {
1051
1040
return { booleanValue : false } ;
1052
- } else if ( type === SpecialMapValueType . MAX_KEY ) {
1041
+ } else if ( type === MapRepresentation . MAX_KEY ) {
1053
1042
return INTERNAL_MAX_VALUE ;
1054
1043
}
1055
1044
return MAX_KEY_VALUE ;
0 commit comments