@@ -78,6 +78,7 @@ static struct module_state _state;
78
78
#define STANDARD 4
79
79
#define JAVA_LEGACY 5
80
80
#define CSHARP_LEGACY 6
81
+ #define UNSPECIFIED 0
81
82
82
83
#define BSON_MAX_SIZE 2147483647
83
84
/* The smallest possible BSON document, i.e. "{}" */
@@ -583,19 +584,6 @@ static int write_element_to_buffer(PyObject* self, buffer_t buffer,
583
584
return result ;
584
585
}
585
586
586
- static void
587
- _fix_java (const char * in , char * out ) {
588
- int i , j ;
589
- for (i = 0 , j = 7 ; i < j ; i ++ , j -- ) {
590
- out [i ] = in [j ];
591
- out [j ] = in [i ];
592
- }
593
- for (i = 8 , j = 15 ; i < j ; i ++ , j -- ) {
594
- out [i ] = in [j ];
595
- out [j ] = in [i ];
596
- }
597
- }
598
-
599
587
static void
600
588
_set_cannot_encode (PyObject * value ) {
601
589
PyObject * type = NULL ;
@@ -1276,73 +1264,35 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
1276
1264
1277
1265
uuid_type = _get_object (state -> UUID , "uuid" , "UUID" );
1278
1266
if (uuid_type && PyObject_IsInstance (value , uuid_type )) {
1279
- /* Just a special case of Binary above, but
1280
- * simpler to do as a separate case. */
1281
- PyObject * bytes ;
1282
- /* Could be bytes, bytearray, str... */
1283
- const char * data ;
1284
- /* UUID is always 16 bytes */
1285
- int size = 16 ;
1286
- char subtype ;
1267
+ PyObject * binary_type = NULL ;
1268
+ PyObject * binary_value = NULL ;
1269
+ int result ;
1287
1270
1288
1271
Py_DECREF (uuid_type );
1289
1272
/* PyObject_IsInstance returns -1 on error */
1290
1273
if (PyErr_Occurred ()) {
1291
1274
return 0 ;
1292
1275
}
1293
1276
1294
- if (options -> uuid_rep == JAVA_LEGACY
1295
- || options -> uuid_rep == CSHARP_LEGACY ) {
1296
- subtype = 3 ;
1297
- }
1298
- else {
1299
- subtype = options -> uuid_rep ;
1300
- }
1301
-
1302
- * (buffer_get_buffer (buffer ) + type_byte ) = 0x05 ;
1303
- if (!buffer_write_int32 (buffer , (int32_t )size )) {
1304
- return 0 ;
1305
- }
1306
- if (!buffer_write_bytes (buffer , & subtype , 1 )) {
1277
+ binary_type = _get_object (state -> Binary , "bson" , "Binary" );
1278
+ if (binary_type == NULL ) {
1307
1279
return 0 ;
1308
1280
}
1309
1281
1310
- if (options -> uuid_rep == CSHARP_LEGACY ) {
1311
- /* Legacy C# byte order */
1312
- bytes = PyObject_GetAttrString (value , "bytes_le" );
1313
- }
1314
- else {
1315
- bytes = PyObject_GetAttrString (value , "bytes" );
1316
- }
1317
- if (!bytes ) {
1318
- return 0 ;
1319
- }
1320
- #if PY_MAJOR_VERSION >= 3
1321
- data = PyBytes_AsString (bytes );
1322
- #else
1323
- data = PyString_AsString (bytes );
1324
- #endif
1325
- if (data == NULL ) {
1326
- Py_DECREF (bytes );
1282
+ binary_value = PyObject_CallMethod (binary_type , "from_uuid" , "(Oi)" , value , options -> uuid_rep );
1283
+ if (binary_value == NULL ) {
1284
+ Py_DECREF (binary_type );
1327
1285
return 0 ;
1328
1286
}
1329
- if (options -> uuid_rep == JAVA_LEGACY ) {
1330
- /* Store in legacy java byte order. */
1331
- char as_legacy_java [16 ];
1332
- _fix_java (data , as_legacy_java );
1333
- if (!buffer_write_bytes (buffer , as_legacy_java , size )) {
1334
- Py_DECREF (bytes );
1335
- return 0 ;
1336
- }
1337
- }
1338
- else {
1339
- if (!buffer_write_bytes (buffer , data , size )) {
1340
- Py_DECREF (bytes );
1341
- return 0 ;
1342
- }
1343
- }
1344
- Py_DECREF (bytes );
1345
- return 1 ;
1287
+
1288
+ result = _write_element_to_buffer (self , buffer ,
1289
+ type_byte , binary_value ,
1290
+ check_keys , options ,
1291
+ in_custom_call ,
1292
+ in_fallback_call );
1293
+ Py_DECREF (binary_type );
1294
+ Py_DECREF (binary_value );
1295
+ return result ;
1346
1296
}
1347
1297
Py_XDECREF (mapping_type );
1348
1298
Py_XDECREF (uuid_type );
@@ -1823,7 +1773,6 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
1823
1773
unsigned * position , unsigned char type ,
1824
1774
unsigned max , const codec_options_t * options ) {
1825
1775
struct module_state * state = GETSTATE (self );
1826
-
1827
1776
PyObject * value = NULL ;
1828
1777
switch (type ) {
1829
1778
case 1 :
@@ -2063,70 +2012,49 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
2063
2012
if (!data ) {
2064
2013
goto invalid ;
2065
2014
}
2066
- /* Encode as UUID, not Binary */
2015
+ /* Encode as UUID or Binary based on options->uuid_rep
2016
+ * TODO: PYTHON-2245 Decoding should follow UUID spec in PyMongo 4.0 */
2067
2017
if (subtype == 3 || subtype == 4 ) {
2068
- PyObject * kwargs ;
2069
- PyObject * args = PyTuple_New (0 );
2018
+ PyObject * binary_type = NULL ;
2019
+ PyObject * binary_value = NULL ;
2020
+ char uuid_rep = options -> uuid_rep ;
2021
+
2070
2022
/* UUID should always be 16 bytes */
2071
- if (!args || length != 16 ) {
2072
- Py_DECREF (data );
2073
- goto invalid ;
2074
- }
2075
- kwargs = PyDict_New ();
2076
- if (!kwargs ) {
2077
- Py_DECREF (data );
2078
- Py_DECREF (args );
2079
- goto invalid ;
2023
+ if (length != 16 ) {
2024
+ goto uuiderror ;
2080
2025
}
2081
2026
2082
- /*
2083
- * From this point, we hold refs to args, kwargs, and data.
2084
- * If anything fails, goto uuiderror to clean them up.
2085
- */
2086
- if (subtype == 3 && options -> uuid_rep == CSHARP_LEGACY ) {
2087
- /* Legacy C# byte order */
2088
- if ((PyDict_SetItemString (kwargs , "bytes_le" , data )) == -1 )
2089
- goto uuiderror ;
2027
+ binary_type = _get_object (state -> Binary , "bson" , "Binary" );
2028
+ if (binary_type == NULL ) {
2029
+ goto uuiderror ;
2090
2030
}
2091
- else {
2092
- if (subtype == 3 && options -> uuid_rep == JAVA_LEGACY ) {
2093
- /* Convert from legacy java byte order */
2094
- char big_endian [16 ];
2095
- _fix_java (buffer + * position , big_endian );
2096
- /* Free the previously created PyString object */
2097
- Py_DECREF (data );
2098
- #if PY_MAJOR_VERSION >= 3
2099
- data = PyBytes_FromStringAndSize (big_endian , length );
2100
- #else
2101
- data = PyString_FromStringAndSize (big_endian , length );
2102
- #endif
2103
- if (data == NULL )
2104
- goto uuiderror ;
2105
- }
2106
- if ((PyDict_SetItemString (kwargs , "bytes" , data )) == -1 )
2107
- goto uuiderror ;
2108
2031
2032
+ binary_value = PyObject_CallFunction (binary_type , "(Oi)" , data , subtype );
2033
+ if (binary_value == NULL ) {
2034
+ goto uuiderror ;
2109
2035
}
2110
- if ((type_to_create = _get_object (state -> UUID , "uuid" , "UUID" ))) {
2111
- value = PyObject_Call (type_to_create , args , kwargs );
2112
- Py_DECREF (type_to_create );
2036
+
2037
+ if (uuid_rep == UNSPECIFIED ) {
2038
+ value = binary_value ;
2039
+ Py_INCREF (value );
2040
+ } else {
2041
+ if (subtype == 4 ) {
2042
+ uuid_rep = STANDARD ;
2043
+ } else if (uuid_rep == STANDARD ) {
2044
+ uuid_rep = PYTHON_LEGACY ;
2045
+ }
2046
+ value = PyObject_CallMethod (binary_value , "as_uuid" , "(i)" , uuid_rep );
2113
2047
}
2114
2048
2115
- Py_DECREF (args );
2116
- Py_DECREF (kwargs );
2049
+ uuiderror :
2050
+ Py_XDECREF (binary_type );
2051
+ Py_XDECREF (binary_value );
2117
2052
Py_DECREF (data );
2118
2053
if (!value ) {
2119
2054
goto invalid ;
2120
2055
}
2121
-
2122
2056
* position += length ;
2123
2057
break ;
2124
-
2125
- uuiderror :
2126
- Py_DECREF (args );
2127
- Py_DECREF (kwargs );
2128
- Py_XDECREF (data );
2129
- goto invalid ;
2130
2058
}
2131
2059
2132
2060
#if PY_MAJOR_VERSION >= 3
0 commit comments