@@ -602,86 +602,16 @@ static int write_element_to_buffer(bson_buffer* buffer, int type_byte, PyObject*
602602 }
603603 return 1 ;
604604 } else if (PyObject_IsInstance (value , DBRef )) {
605- int start_position ,
606- length_location ,
607- collection_length ,
608- type_pos ,
609- length ;
610- PyObject * collection_object ;
611- PyObject * encoded_collection ;
612- PyObject * id_object ;
613- char zero = 0 ;
614-
615- * (buffer -> buffer + type_byte ) = 0x03 ;
616- start_position = buffer -> position ;
617-
618- /* save space for length */
619- length_location = buffer_save_bytes (buffer , 4 );
620- if (length_location == -1 ) {
605+ PyObject * as_doc = PyObject_CallMethod (value , "as_doc" , NULL );
606+ if (!as_doc ) {
621607 return 0 ;
622608 }
623-
624- collection_object = PyObject_GetAttrString (value , "collection" );
625- if (!collection_object ) {
609+ if (!write_dict (buffer , as_doc , 0 )) {
610+ Py_DECREF (as_doc );
626611 return 0 ;
627612 }
628- encoded_collection = PyUnicode_AsUTF8String (collection_object );
629- Py_DECREF (collection_object );
630- if (!encoded_collection ) {
631- return 0 ;
632- }
633- {
634- const char * collection = PyString_AsString (encoded_collection );
635- if (!collection ) {
636- Py_DECREF (encoded_collection );
637- return 0 ;
638- }
639- id_object = PyObject_GetAttrString (value , "id" );
640- if (!id_object ) {
641- Py_DECREF (encoded_collection );
642- return 0 ;
643- }
644-
645- if (!buffer_write_bytes (buffer , "\x02$ref\x00" , 6 )) {
646- Py_DECREF (encoded_collection );
647- Py_DECREF (id_object );
648- return 0 ;
649- }
650- collection_length = strlen (collection ) + 1 ;
651- if (!buffer_write_bytes (buffer , (const char * )& collection_length , 4 )) {
652- Py_DECREF (encoded_collection );
653- Py_DECREF (id_object );
654- return 0 ;
655- }
656- if (!buffer_write_bytes (buffer , collection , collection_length )) {
657- Py_DECREF (encoded_collection );
658- Py_DECREF (id_object );
659- return 0 ;
660- }
661- }
662- Py_DECREF (encoded_collection );
663-
664- type_pos = buffer_save_bytes (buffer , 1 );
665- if (type_pos == -1 ) {
666- Py_DECREF (id_object );
667- return 0 ;
668- }
669- if (!buffer_write_bytes (buffer , "$id\x00" , 4 )) {
670- Py_DECREF (id_object );
671- return 0 ;
672- }
673- if (!write_element_to_buffer (buffer , type_pos , id_object , check_keys )) {
674- Py_DECREF (id_object );
675- return 0 ;
676- }
677- Py_DECREF (id_object );
678-
679- /* write null byte and fill in length */
680- if (!buffer_write_bytes (buffer , & zero , 1 )) {
681- return 0 ;
682- }
683- length = buffer -> position - start_position ;
684- memcpy (buffer -> buffer + length_location , & length , 4 );
613+ Py_DECREF (as_doc );
614+ * (buffer -> buffer + type_byte ) = 0x03 ;
685615 return 1 ;
686616 }
687617 else if (PyObject_HasAttrString (value , "pattern" ) &&
@@ -1043,33 +973,22 @@ static PyObject* get_value(const char* buffer, int* position, int type) {
1043973 {
1044974 int size ;
1045975 memcpy (& size , buffer + * position , 4 );
976+ value = elements_to_dict (buffer + * position + 4 , size - 5 );
977+ if (!value ) {
978+ return NULL ;
979+ }
980+
981+ /* Decoding for DBRefs */
1046982 if (strcmp (buffer + * position + 5 , "$ref" ) == 0 ) { /* DBRef */
1047- char id_type ;
1048- PyObject * id ;
983+ PyObject * id = PyDict_GetItemString (value , "$id" );
984+ PyObject * collection = PyDict_GetItemString (value , "$ref" );
985+ PyObject * database = PyDict_GetItemString (value , "$db" );
1049986
1050- int offset = * position + 14 ;
1051- int collection_length = strlen (buffer + offset );
1052- PyObject * collection = PyUnicode_DecodeUTF8 (buffer + offset , collection_length , "strict" );
1053- if (!collection ) {
1054- return NULL ;
1055- }
1056- offset += collection_length + 1 ;
1057- id_type = buffer [offset ];
1058- offset += 5 ;
1059- id = get_value (buffer , & offset , (int )id_type );
1060- if (!id ) {
1061- Py_DECREF (collection );
1062- return NULL ;
1063- }
1064- value = PyObject_CallFunctionObjArgs (DBRef , collection , id , NULL );
1065- Py_DECREF (collection );
1066- Py_DECREF (id );
1067- } else {
1068- value = elements_to_dict (buffer + * position + 4 , size - 5 );
1069- if (!value ) {
1070- return NULL ;
1071- }
987+ /* This works even if there is no $db since database will be NULL and
988+ the call will be as if there were only two arguments specified. */
989+ value = PyObject_CallFunctionObjArgs (DBRef , collection , id , database , NULL );
1072990 }
991+
1073992 * position += size ;
1074993 break ;
1075994 }
0 commit comments