@@ -103,7 +103,8 @@ static const char *read_state_names[] = {FOREACH_READ_STATE (GENERATE_STRING)};
103
103
BS (DECIMAL128 ) \
104
104
BS (DBPOINTER ) \
105
105
BS (SYMBOL ) \
106
- BS (DBREF )
106
+ BS (DBREF ) \
107
+ BS (UUID )
107
108
108
109
typedef enum {
109
110
FOREACH_BSON_STATE (BSON_STATE_ENUM )
@@ -706,6 +707,7 @@ _bson_json_read_integer (bson_json_reader_t *reader, uint64_t val, int64_t sign)
706
707
case BSON_JSON_LF_OID :
707
708
case BSON_JSON_LF_BINARY :
708
709
case BSON_JSON_LF_TYPE :
710
+ case BSON_JSON_LF_UUID :
709
711
case BSON_JSON_LF_UNDEFINED :
710
712
case BSON_JSON_LF_DOUBLE :
711
713
case BSON_JSON_LF_DECIMAL128 :
@@ -833,8 +835,29 @@ _bson_json_read_int64_or_set_error (bson_json_reader_t *reader, /* IN */
833
835
return true;
834
836
}
835
837
838
+ static bool
839
+ _unhexlify_uuid (const char * uuid , uint8_t * out , size_t max )
840
+ {
841
+ unsigned int byte ;
842
+ int x = 0 ;
843
+ int i = 0 ;
844
+
845
+ BSON_ASSERT (strlen (uuid ) == 32 );
846
+
847
+ while (SSCANF (& uuid [i ], "%2x" , & byte ) == 1 ) {
848
+ if (x >= max ) {
849
+ return false;
850
+ }
851
+
852
+ out [x ++ ] = (uint8_t ) byte ;
853
+ i += 2 ;
854
+ }
836
855
837
- /* parse a value for "base64", "subType" or legacy "$binary" or "$type" */
856
+ return i == 32 ;
857
+ }
858
+
859
+ /* parse a value for "base64", "subType", legacy "$binary" or "$type", or
860
+ * "$uuid" */
838
861
static void
839
862
_bson_json_parse_binary_elem (bson_json_reader_t * reader ,
840
863
const char * val_w_null ,
@@ -894,6 +917,64 @@ _bson_json_parse_binary_elem (bson_json_reader_t *reader,
894
917
(int ) vlen );
895
918
}
896
919
}
920
+ } else if (bs == BSON_JSON_LF_UUID ) {
921
+ int nread = 0 ;
922
+ char uuid [33 ];
923
+
924
+ data -> binary .has_binary = true;
925
+ data -> binary .has_subtype = true;
926
+ data -> binary .type = BSON_SUBTYPE_UUID ;
927
+
928
+ /* Validate the UUID and extract relevant portions */
929
+ /* We can't use %x here as it allows +, -, and 0x prefixes */
930
+ #ifdef _MSC_VER
931
+ SSCANF (val_w_null ,
932
+ "%8c-%4c-%4c-%4c-%12c%n" ,
933
+ & uuid [0 ],
934
+ 8 ,
935
+ & uuid [8 ],
936
+ 4 ,
937
+ & uuid [12 ],
938
+ 4 ,
939
+ & uuid [16 ],
940
+ 4 ,
941
+ & uuid [20 ],
942
+ 12 ,
943
+ & nread );
944
+ #else
945
+ SSCANF (val_w_null ,
946
+ "%8c-%4c-%4c-%4c-%12c%n" ,
947
+ & uuid [0 ],
948
+ & uuid [8 ],
949
+ & uuid [12 ],
950
+ & uuid [16 ],
951
+ & uuid [20 ],
952
+ & nread );
953
+ #endif
954
+
955
+ uuid [32 ] = '\0' ;
956
+
957
+ if (nread != 36 || val_w_null [nread ] != '\0' ) {
958
+ _bson_json_read_set_error (reader ,
959
+ "Invalid input string \"%s\", looking for "
960
+ "a dash-separated UUID string" ,
961
+ val_w_null );
962
+
963
+ return ;
964
+ }
965
+
966
+ binary_len = 16 ;
967
+ _bson_json_buf_ensure (& bson -> bson_type_buf [0 ], (size_t ) binary_len + 1 );
968
+
969
+ if (!_unhexlify_uuid (
970
+ & uuid [0 ], bson -> bson_type_buf [0 ].buf , (size_t ) binary_len )) {
971
+ _bson_json_read_set_error (reader ,
972
+ "Invalid input string \"%s\", looking for "
973
+ "a dash-separated UUID string" ,
974
+ val_w_null );
975
+ }
976
+
977
+ bson -> bson_type_buf [0 ].len = (size_t ) binary_len ;
897
978
}
898
979
}
899
980
@@ -967,6 +1048,8 @@ _bson_json_read_string (bson_json_reader_t *reader, /* IN */
967
1048
case BSON_JSON_LF_BINARY :
968
1049
case BSON_JSON_LF_TYPE :
969
1050
bson -> bson_type_data .binary .is_legacy = true;
1051
+ /* FALL THROUGH */
1052
+ case BSON_JSON_LF_UUID :
970
1053
_bson_json_parse_binary_elem (reader , val_w_null , vlen );
971
1054
break ;
972
1055
case BSON_JSON_LF_INT32 : {
@@ -1123,7 +1206,7 @@ _is_known_key (const char *key, size_t len)
1123
1206
IS_KEY ("$numberDouble" ) || IS_KEY ("$numberDecimal" ) ||
1124
1207
IS_KEY ("$numberInt" ) || IS_KEY ("$numberLong" ) ||
1125
1208
IS_KEY ("$numberDouble" ) || IS_KEY ("$numberDecimal" ) ||
1126
- IS_KEY ("$dbPointer" ) || IS_KEY ("$symbol" ));
1209
+ IS_KEY ("$dbPointer" ) || IS_KEY ("$symbol" ) || IS_KEY ( "$uuid" ) );
1127
1210
1128
1211
#undef IS_KEY
1129
1212
@@ -1241,6 +1324,8 @@ _bson_json_read_map_key (bson_json_reader_t *reader, /* IN */
1241
1324
HANDLE_OPTION ("$binary" , BSON_TYPE_BINARY , BSON_JSON_LF_BINARY )
1242
1325
else if
1243
1326
HANDLE_OPTION ("$type" , BSON_TYPE_BINARY , BSON_JSON_LF_TYPE )
1327
+ else if
1328
+ HANDLE_OPTION ("$uuid" , BSON_TYPE_BINARY , BSON_JSON_LF_UUID )
1244
1329
else if
1245
1330
HANDLE_OPTION ("$date" , BSON_TYPE_DATE_TIME , BSON_JSON_LF_DATE )
1246
1331
else if
0 commit comments