bson 4.2.2 → 4.3.0.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ext/bson/bson_native.c +527 -19
- data/lib/bson/array.rb +22 -14
- data/lib/bson/hash.rb +22 -14
- data/lib/bson/registry.rb +2 -2
- data/lib/bson/symbol.rb +1 -1
- data/lib/bson/timestamp.rb +24 -0
- data/lib/bson/version.rb +1 -1
- data/spec/bson/byte_buffer_spec.rb +21 -7
- data/spec/bson/document_spec.rb +18 -0
- data/spec/bson/timestamp_spec.rb +55 -0
- data/spec/spec_helper.rb +1 -0
- metadata +2 -2
- metadata.gz.sig +0 -0
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3a8c878410e043f1b920f996932401686eb2ef59
         | 
| 4 | 
            +
              data.tar.gz: e459f34a04cbc3cc71f4723e95225fc69af98796
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e0ba9d2a810a8dd77520b0605b351dfc9c06525dab2998f77755480e1600a2d799dd6ca2084268a903e335e4336b6c96a829c2943cc2f7adeea55ee8b1bf1f15
         | 
| 7 | 
            +
              data.tar.gz: 54c0d9e149895d20f857273a392d4895b55c61f2642d5c6561a0ce2478707f56a0bf810c8ea5220a1fbdf1b69d59f6ce0ced391cbd00e7dd4f8b25ade6418d6d
         | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | Binary file | 
    
        data.tar.gz.sig
    CHANGED
    
    | Binary file | 
    
        data/ext/bson/bson_native.c
    CHANGED
    
    | @@ -26,6 +26,14 @@ | |
| 26 26 | 
             
            #define HOST_NAME_HASH_MAX 256
         | 
| 27 27 | 
             
            #endif
         | 
| 28 28 |  | 
| 29 | 
            +
            #define BSON_TYPE_DOUBLE 1
         | 
| 30 | 
            +
            #define BSON_TYPE_STRING 2
         | 
| 31 | 
            +
            #define BSON_TYPE_OBJECT 3
         | 
| 32 | 
            +
            #define BSON_TYPE_ARRAY 4
         | 
| 33 | 
            +
            #define BSON_TYPE_INT32 16
         | 
| 34 | 
            +
            #define BSON_TYPE_INT64 18
         | 
| 35 | 
            +
            #define BSON_TYPE_BOOLEAN 8
         | 
| 36 | 
            +
             | 
| 29 37 | 
             
            typedef struct {
         | 
| 30 38 | 
             
              size_t size;
         | 
| 31 39 | 
             
              size_t write_position;
         | 
| @@ -61,6 +69,8 @@ static VALUE rb_bson_byte_buffer_get_double(VALUE self); | |
| 61 69 | 
             
            static VALUE rb_bson_byte_buffer_get_int32(VALUE self);
         | 
| 62 70 | 
             
            static VALUE rb_bson_byte_buffer_get_int64(VALUE self);
         | 
| 63 71 | 
             
            static VALUE rb_bson_byte_buffer_get_string(VALUE self);
         | 
| 72 | 
            +
            static VALUE rb_bson_byte_buffer_get_hash(VALUE self);
         | 
| 73 | 
            +
            static VALUE rb_bson_byte_buffer_get_array(VALUE self);
         | 
| 64 74 | 
             
            static VALUE rb_bson_byte_buffer_put_byte(VALUE self, VALUE byte);
         | 
| 65 75 | 
             
            static VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes);
         | 
| 66 76 | 
             
            static VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string);
         | 
| @@ -69,6 +79,8 @@ static VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f); | |
| 69 79 | 
             
            static VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i);
         | 
| 70 80 | 
             
            static VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i);
         | 
| 71 81 | 
             
            static VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string);
         | 
| 82 | 
            +
            static VALUE rb_bson_byte_buffer_put_hash(VALUE self, VALUE hash, VALUE validating_keys);
         | 
| 83 | 
            +
            static VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_keys);
         | 
| 72 84 | 
             
            static VALUE rb_bson_byte_buffer_read_position(VALUE self);
         | 
| 73 85 | 
             
            static VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i);
         | 
| 74 86 | 
             
            static VALUE rb_bson_byte_buffer_rewind(VALUE self);
         | 
| @@ -87,6 +99,28 @@ static const rb_data_type_t rb_byte_buffer_data_type = { | |
| 87 99 | 
             
              { NULL, rb_bson_byte_buffer_free, rb_bson_byte_buffer_memsize }
         | 
| 88 100 | 
             
            };
         | 
| 89 101 |  | 
| 102 | 
            +
            static uint8_t pvt_get_type_byte(byte_buffer_t *b);
         | 
| 103 | 
            +
            static VALUE pvt_get_int32(byte_buffer_t *b);
         | 
| 104 | 
            +
            static VALUE pvt_get_int64(byte_buffer_t *b);
         | 
| 105 | 
            +
            static VALUE pvt_get_double(byte_buffer_t *b);
         | 
| 106 | 
            +
            static VALUE pvt_get_string(byte_buffer_t *b);
         | 
| 107 | 
            +
            static VALUE pvt_get_boolean(byte_buffer_t *b);
         | 
| 108 | 
            +
             | 
| 109 | 
            +
             | 
| 110 | 
            +
            static VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type);
         | 
| 111 | 
            +
            static void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval);
         | 
| 112 | 
            +
            static void pvt_skip_cstring(byte_buffer_t *b);
         | 
| 113 | 
            +
            static void pvt_validate_length(byte_buffer_t *b);
         | 
| 114 | 
            +
             | 
| 115 | 
            +
             | 
| 116 | 
            +
            static void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys);
         | 
| 117 | 
            +
            static void pvt_put_byte(byte_buffer_t *b, const char byte);
         | 
| 118 | 
            +
            static void pvt_put_int32(byte_buffer_t *b, const int32_t i32);
         | 
| 119 | 
            +
            static void pvt_put_int64(byte_buffer_t *b, const int64_t i);
         | 
| 120 | 
            +
            static void pvt_put_double(byte_buffer_t *b, double f);
         | 
| 121 | 
            +
            static void pvt_put_cstring(byte_buffer_t *b, VALUE string);
         | 
| 122 | 
            +
            static void pvt_put_bson_key(byte_buffer_t *b, VALUE string, VALUE validating_keys);
         | 
| 123 | 
            +
             | 
| 90 124 | 
             
            /**
         | 
| 91 125 | 
             
             * Holds the machine id hash for object id generation.
         | 
| 92 126 | 
             
             */
         | 
| @@ -97,6 +131,10 @@ static char rb_bson_machine_id_hash[HOST_NAME_HASH_MAX]; | |
| 97 131 | 
             
             */
         | 
| 98 132 | 
             
            static uint32_t rb_bson_object_id_counter;
         | 
| 99 133 |  | 
| 134 | 
            +
             | 
| 135 | 
            +
            static VALUE rb_bson_registry;
         | 
| 136 | 
            +
             | 
| 137 | 
            +
            static VALUE rb_bson_illegal_key;
         | 
| 100 138 | 
             
            /**
         | 
| 101 139 | 
             
             * Initialize the bson_native extension.
         | 
| 102 140 | 
             
             */
         | 
| @@ -111,6 +149,8 @@ void Init_bson_native() | |
| 111 149 | 
             
              VALUE rb_digest_class = rb_const_get(rb_cObject, rb_intern("Digest"));
         | 
| 112 150 | 
             
              VALUE rb_md5_class = rb_const_get(rb_digest_class, rb_intern("MD5"));
         | 
| 113 151 |  | 
| 152 | 
            +
              rb_bson_illegal_key = rb_const_get(rb_const_get(rb_bson_module, rb_intern("String")),rb_intern("IllegalKey"));
         | 
| 153 | 
            +
             | 
| 114 154 | 
             
              rb_define_alloc_func(rb_byte_buffer_class, rb_bson_byte_buffer_allocate);
         | 
| 115 155 | 
             
              rb_define_method(rb_byte_buffer_class, "initialize", rb_bson_byte_buffer_initialize, -1);
         | 
| 116 156 | 
             
              rb_define_method(rb_byte_buffer_class, "length", rb_bson_byte_buffer_length, 0);
         | 
| @@ -119,6 +159,9 @@ void Init_bson_native() | |
| 119 159 | 
             
              rb_define_method(rb_byte_buffer_class, "get_cstring", rb_bson_byte_buffer_get_cstring, 0);
         | 
| 120 160 | 
             
              rb_define_method(rb_byte_buffer_class, "get_decimal128_bytes", rb_bson_byte_buffer_get_decimal128_bytes, 0);
         | 
| 121 161 | 
             
              rb_define_method(rb_byte_buffer_class, "get_double", rb_bson_byte_buffer_get_double, 0);
         | 
| 162 | 
            +
              rb_define_method(rb_byte_buffer_class, "get_hash", rb_bson_byte_buffer_get_hash, 0);
         | 
| 163 | 
            +
              rb_define_method(rb_byte_buffer_class, "get_array", rb_bson_byte_buffer_get_array, 0);
         | 
| 164 | 
            +
             | 
| 122 165 | 
             
              rb_define_method(rb_byte_buffer_class, "get_int32", rb_bson_byte_buffer_get_int32, 0);
         | 
| 123 166 | 
             
              rb_define_method(rb_byte_buffer_class, "get_int64", rb_bson_byte_buffer_get_int64, 0);
         | 
| 124 167 | 
             
              rb_define_method(rb_byte_buffer_class, "get_string", rb_bson_byte_buffer_get_string, 0);
         | 
| @@ -137,6 +180,9 @@ void Init_bson_native() | |
| 137 180 | 
             
              rb_define_method(rb_byte_buffer_class, "to_s", rb_bson_byte_buffer_to_s, 0);
         | 
| 138 181 | 
             
              rb_define_method(rb_bson_object_id_generator_class, "next_object_id", rb_bson_object_id_generator_next, -1);
         | 
| 139 182 |  | 
| 183 | 
            +
              rb_define_method(rb_byte_buffer_class, "put_hash", rb_bson_byte_buffer_put_hash, 2);
         | 
| 184 | 
            +
              rb_define_method(rb_byte_buffer_class, "put_array", rb_bson_byte_buffer_put_array, 2);
         | 
| 185 | 
            +
             | 
| 140 186 | 
             
              // Get the object id machine id and hash it.
         | 
| 141 187 | 
             
              rb_require("digest/md5");
         | 
| 142 188 | 
             
              gethostname(rb_bson_machine_id, sizeof(rb_bson_machine_id));
         | 
| @@ -145,6 +191,8 @@ void Init_bson_native() | |
| 145 191 |  | 
| 146 192 | 
             
              // Set the object id counter to a random number
         | 
| 147 193 | 
             
              rb_bson_object_id_counter = FIX2INT(rb_funcall(rb_mKernel, rb_intern("rand"), 1, INT2FIX(0x1000000)));
         | 
| 194 | 
            +
             | 
| 195 | 
            +
              rb_bson_registry = rb_const_get(rb_bson_module, rb_intern("Registry"));
         | 
| 148 196 | 
             
            }
         | 
| 149 197 |  | 
| 150 198 | 
             
            void rb_bson_generate_machine_id(VALUE rb_md5_class, char *rb_bson_machine_id)
         | 
| @@ -180,6 +228,285 @@ VALUE rb_bson_byte_buffer_initialize(int argc, VALUE *argv, VALUE self) | |
| 180 228 | 
             
              return self;
         | 
| 181 229 | 
             
            }
         | 
| 182 230 |  | 
| 231 | 
            +
            static int fits_int32(int64_t i64){
         | 
| 232 | 
            +
              return i64 >= INT32_MIN && i64 <= INT32_MAX;
         | 
| 233 | 
            +
            }
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            /* write the byte denoting the BSON type for the passed object*/
         | 
| 236 | 
            +
            void pvt_put_type_byte(byte_buffer_t *b, VALUE val){
         | 
| 237 | 
            +
              switch(TYPE(val)){
         | 
| 238 | 
            +
                case T_BIGNUM:
         | 
| 239 | 
            +
                case T_FIXNUM:
         | 
| 240 | 
            +
                  if(fits_int32(NUM2LL(val))){
         | 
| 241 | 
            +
                    pvt_put_byte(b, BSON_TYPE_INT32);
         | 
| 242 | 
            +
                  }else{
         | 
| 243 | 
            +
                    pvt_put_byte(b, BSON_TYPE_INT64);
         | 
| 244 | 
            +
                  }
         | 
| 245 | 
            +
                  break;
         | 
| 246 | 
            +
                case T_STRING:
         | 
| 247 | 
            +
                  pvt_put_byte(b, BSON_TYPE_STRING);
         | 
| 248 | 
            +
                  break;
         | 
| 249 | 
            +
                case T_ARRAY:
         | 
| 250 | 
            +
                  pvt_put_byte(b, BSON_TYPE_ARRAY);
         | 
| 251 | 
            +
                  break;
         | 
| 252 | 
            +
                case T_TRUE:
         | 
| 253 | 
            +
                case T_FALSE:
         | 
| 254 | 
            +
                  pvt_put_byte(b, BSON_TYPE_BOOLEAN);
         | 
| 255 | 
            +
                  break;
         | 
| 256 | 
            +
                case T_HASH:
         | 
| 257 | 
            +
                  pvt_put_byte(b, BSON_TYPE_OBJECT);
         | 
| 258 | 
            +
                  break;
         | 
| 259 | 
            +
                case T_FLOAT:
         | 
| 260 | 
            +
                  pvt_put_byte(b, BSON_TYPE_DOUBLE);
         | 
| 261 | 
            +
                  break;
         | 
| 262 | 
            +
                default:{
         | 
| 263 | 
            +
                  VALUE type = rb_funcall(val, rb_intern("bson_type"),0);
         | 
| 264 | 
            +
                  pvt_put_byte(b, *RSTRING_PTR(type));
         | 
| 265 | 
            +
                  break;
         | 
| 266 | 
            +
                }
         | 
| 267 | 
            +
              }
         | 
| 268 | 
            +
            }
         | 
| 269 | 
            +
             | 
| 270 | 
            +
            void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys){
         | 
| 271 | 
            +
              switch(TYPE(val)){
         | 
| 272 | 
            +
                case T_BIGNUM:
         | 
| 273 | 
            +
                case T_FIXNUM:{
         | 
| 274 | 
            +
                  int64_t i64= NUM2LL(val);
         | 
| 275 | 
            +
                  if(fits_int32(i64)){
         | 
| 276 | 
            +
                    pvt_put_int32(b, (int32_t)i64);
         | 
| 277 | 
            +
                  }else{
         | 
| 278 | 
            +
                    pvt_put_int64(b, i64);
         | 
| 279 | 
            +
                  }
         | 
| 280 | 
            +
                  break;
         | 
| 281 | 
            +
                }
         | 
| 282 | 
            +
                case T_FLOAT:
         | 
| 283 | 
            +
                  pvt_put_double(b, NUM2DBL(val));
         | 
| 284 | 
            +
                  break;
         | 
| 285 | 
            +
                case T_ARRAY:
         | 
| 286 | 
            +
                  rb_bson_byte_buffer_put_array(rb_buffer, val, validating_keys);
         | 
| 287 | 
            +
                  break;
         | 
| 288 | 
            +
                case T_TRUE:
         | 
| 289 | 
            +
                  pvt_put_byte(b, 1);
         | 
| 290 | 
            +
                  break;
         | 
| 291 | 
            +
                case T_FALSE:
         | 
| 292 | 
            +
                  pvt_put_byte(b, 0);
         | 
| 293 | 
            +
                  break;
         | 
| 294 | 
            +
                case T_HASH:
         | 
| 295 | 
            +
                  rb_bson_byte_buffer_put_hash(rb_buffer, val, validating_keys);
         | 
| 296 | 
            +
                  break;
         | 
| 297 | 
            +
                default:{
         | 
| 298 | 
            +
                  rb_funcall(val, rb_intern("to_bson"), 2, rb_buffer, validating_keys);
         | 
| 299 | 
            +
                  break;
         | 
| 300 | 
            +
                }
         | 
| 301 | 
            +
              }
         | 
| 302 | 
            +
            }
         | 
| 303 | 
            +
             | 
| 304 | 
            +
            typedef struct{
         | 
| 305 | 
            +
              byte_buffer_t *b;
         | 
| 306 | 
            +
              VALUE buffer;
         | 
| 307 | 
            +
              VALUE validating_keys;
         | 
| 308 | 
            +
            } put_hash_context;
         | 
| 309 | 
            +
             | 
| 310 | 
            +
            static int put_hash_callback(VALUE key, VALUE val, VALUE context){
         | 
| 311 | 
            +
              VALUE buffer = ((put_hash_context*)context)->buffer;
         | 
| 312 | 
            +
              VALUE validating_keys = ((put_hash_context*)context)->validating_keys;
         | 
| 313 | 
            +
              byte_buffer_t *b = ((put_hash_context*)context)->b;
         | 
| 314 | 
            +
             | 
| 315 | 
            +
              pvt_put_type_byte(b, val);
         | 
| 316 | 
            +
             | 
| 317 | 
            +
              switch(TYPE(key)){
         | 
| 318 | 
            +
                case T_STRING:
         | 
| 319 | 
            +
                  pvt_put_bson_key(b, key, validating_keys);
         | 
| 320 | 
            +
                  break;
         | 
| 321 | 
            +
                case T_SYMBOL:
         | 
| 322 | 
            +
                  pvt_put_bson_key(b, rb_sym_to_s(key), validating_keys);
         | 
| 323 | 
            +
                  break;
         | 
| 324 | 
            +
                default:
         | 
| 325 | 
            +
                  rb_bson_byte_buffer_put_cstring(buffer, rb_funcall(key, rb_intern("to_bson_key"), 1, validating_keys));
         | 
| 326 | 
            +
              }
         | 
| 327 | 
            +
             | 
| 328 | 
            +
              pvt_put_field(b, buffer, val, validating_keys);
         | 
| 329 | 
            +
              return ST_CONTINUE;
         | 
| 330 | 
            +
            }
         | 
| 331 | 
            +
             | 
| 332 | 
            +
            /**
         | 
| 333 | 
            +
             * serializes a hash into the byte buffer
         | 
| 334 | 
            +
             */
         | 
| 335 | 
            +
            VALUE rb_bson_byte_buffer_put_hash(VALUE self, VALUE hash, VALUE validating_keys){
         | 
| 336 | 
            +
              byte_buffer_t *b = NULL;
         | 
| 337 | 
            +
              put_hash_context context = {0};
         | 
| 338 | 
            +
              size_t position = 0;
         | 
| 339 | 
            +
              size_t new_position = 0;
         | 
| 340 | 
            +
              int32_t new_length = 0;
         | 
| 341 | 
            +
             | 
| 342 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 343 | 
            +
              Check_Type(hash, T_HASH);
         | 
| 344 | 
            +
             | 
| 345 | 
            +
              position = READ_SIZE(b);
         | 
| 346 | 
            +
             | 
| 347 | 
            +
              /* insert length placeholder */
         | 
| 348 | 
            +
              pvt_put_int32(b, 0);
         | 
| 349 | 
            +
              context.buffer = self;
         | 
| 350 | 
            +
              context.validating_keys = validating_keys;
         | 
| 351 | 
            +
              context.b = b;
         | 
| 352 | 
            +
             | 
| 353 | 
            +
              rb_hash_foreach(hash, put_hash_callback, (VALUE)&context);
         | 
| 354 | 
            +
              pvt_put_byte(b, 0);
         | 
| 355 | 
            +
             | 
| 356 | 
            +
              /* update length placeholder with actual value */
         | 
| 357 | 
            +
              new_position = READ_SIZE(b);
         | 
| 358 | 
            +
              new_length = new_position - position;
         | 
| 359 | 
            +
              pvt_replace_int32(b, position, new_length);
         | 
| 360 | 
            +
             | 
| 361 | 
            +
              return self;
         | 
| 362 | 
            +
            }
         | 
| 363 | 
            +
             | 
| 364 | 
            +
            static const char *index_strings[] = {
         | 
| 365 | 
            +
               "0",   "1",   "2",   "3",   "4",   "5",   "6",   "7",   "8",   "9",   "10",
         | 
| 366 | 
            +
               "11",  "12",  "13",  "14",  "15",  "16",  "17",  "18",  "19",  "20",  "21",
         | 
| 367 | 
            +
               "22",  "23",  "24",  "25",  "26",  "27",  "28",  "29",  "30",  "31",  "32",
         | 
| 368 | 
            +
               "33",  "34",  "35",  "36",  "37",  "38",  "39",  "40",  "41",  "42",  "43",
         | 
| 369 | 
            +
               "44",  "45",  "46",  "47",  "48",  "49",  "50",  "51",  "52",  "53",  "54",
         | 
| 370 | 
            +
               "55",  "56",  "57",  "58",  "59",  "60",  "61",  "62",  "63",  "64",  "65",
         | 
| 371 | 
            +
               "66",  "67",  "68",  "69",  "70",  "71",  "72",  "73",  "74",  "75",  "76",
         | 
| 372 | 
            +
               "77",  "78",  "79",  "80",  "81",  "82",  "83",  "84",  "85",  "86",  "87",
         | 
| 373 | 
            +
               "88",  "89",  "90",  "91",  "92",  "93",  "94",  "95",  "96",  "97",  "98",
         | 
| 374 | 
            +
               "99",  "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
         | 
| 375 | 
            +
               "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "120",
         | 
| 376 | 
            +
               "121", "122", "123", "124", "125", "126", "127", "128", "129", "130", "131",
         | 
| 377 | 
            +
               "132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142",
         | 
| 378 | 
            +
               "143", "144", "145", "146", "147", "148", "149", "150", "151", "152", "153",
         | 
| 379 | 
            +
               "154", "155", "156", "157", "158", "159", "160", "161", "162", "163", "164",
         | 
| 380 | 
            +
               "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175",
         | 
| 381 | 
            +
               "176", "177", "178", "179", "180", "181", "182", "183", "184", "185", "186",
         | 
| 382 | 
            +
               "187", "188", "189", "190", "191", "192", "193", "194", "195", "196", "197",
         | 
| 383 | 
            +
               "198", "199", "200", "201", "202", "203", "204", "205", "206", "207", "208",
         | 
| 384 | 
            +
               "209", "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
         | 
| 385 | 
            +
               "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", "230",
         | 
| 386 | 
            +
               "231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241",
         | 
| 387 | 
            +
               "242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252",
         | 
| 388 | 
            +
               "253", "254", "255", "256", "257", "258", "259", "260", "261", "262", "263",
         | 
| 389 | 
            +
               "264", "265", "266", "267", "268", "269", "270", "271", "272", "273", "274",
         | 
| 390 | 
            +
               "275", "276", "277", "278", "279", "280", "281", "282", "283", "284", "285",
         | 
| 391 | 
            +
               "286", "287", "288", "289", "290", "291", "292", "293", "294", "295", "296",
         | 
| 392 | 
            +
               "297", "298", "299", "300", "301", "302", "303", "304", "305", "306", "307",
         | 
| 393 | 
            +
               "308", "309", "310", "311", "312", "313", "314", "315", "316", "317", "318",
         | 
| 394 | 
            +
               "319", "320", "321", "322", "323", "324", "325", "326", "327", "328", "329",
         | 
| 395 | 
            +
               "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", "340",
         | 
| 396 | 
            +
               "341", "342", "343", "344", "345", "346", "347", "348", "349", "350", "351",
         | 
| 397 | 
            +
               "352", "353", "354", "355", "356", "357", "358", "359", "360", "361", "362",
         | 
| 398 | 
            +
               "363", "364", "365", "366", "367", "368", "369", "370", "371", "372", "373",
         | 
| 399 | 
            +
               "374", "375", "376", "377", "378", "379", "380", "381", "382", "383", "384",
         | 
| 400 | 
            +
               "385", "386", "387", "388", "389", "390", "391", "392", "393", "394", "395",
         | 
| 401 | 
            +
               "396", "397", "398", "399", "400", "401", "402", "403", "404", "405", "406",
         | 
| 402 | 
            +
               "407", "408", "409", "410", "411", "412", "413", "414", "415", "416", "417",
         | 
| 403 | 
            +
               "418", "419", "420", "421", "422", "423", "424", "425", "426", "427", "428",
         | 
| 404 | 
            +
               "429", "430", "431", "432", "433", "434", "435", "436", "437", "438", "439",
         | 
| 405 | 
            +
               "440", "441", "442", "443", "444", "445", "446", "447", "448", "449", "450",
         | 
| 406 | 
            +
               "451", "452", "453", "454", "455", "456", "457", "458", "459", "460", "461",
         | 
| 407 | 
            +
               "462", "463", "464", "465", "466", "467", "468", "469", "470", "471", "472",
         | 
| 408 | 
            +
               "473", "474", "475", "476", "477", "478", "479", "480", "481", "482", "483",
         | 
| 409 | 
            +
               "484", "485", "486", "487", "488", "489", "490", "491", "492", "493", "494",
         | 
| 410 | 
            +
               "495", "496", "497", "498", "499", "500", "501", "502", "503", "504", "505",
         | 
| 411 | 
            +
               "506", "507", "508", "509", "510", "511", "512", "513", "514", "515", "516",
         | 
| 412 | 
            +
               "517", "518", "519", "520", "521", "522", "523", "524", "525", "526", "527",
         | 
| 413 | 
            +
               "528", "529", "530", "531", "532", "533", "534", "535", "536", "537", "538",
         | 
| 414 | 
            +
               "539", "540", "541", "542", "543", "544", "545", "546", "547", "548", "549",
         | 
| 415 | 
            +
               "550", "551", "552", "553", "554", "555", "556", "557", "558", "559", "560",
         | 
| 416 | 
            +
               "561", "562", "563", "564", "565", "566", "567", "568", "569", "570", "571",
         | 
| 417 | 
            +
               "572", "573", "574", "575", "576", "577", "578", "579", "580", "581", "582",
         | 
| 418 | 
            +
               "583", "584", "585", "586", "587", "588", "589", "590", "591", "592", "593",
         | 
| 419 | 
            +
               "594", "595", "596", "597", "598", "599", "600", "601", "602", "603", "604",
         | 
| 420 | 
            +
               "605", "606", "607", "608", "609", "610", "611", "612", "613", "614", "615",
         | 
| 421 | 
            +
               "616", "617", "618", "619", "620", "621", "622", "623", "624", "625", "626",
         | 
| 422 | 
            +
               "627", "628", "629", "630", "631", "632", "633", "634", "635", "636", "637",
         | 
| 423 | 
            +
               "638", "639", "640", "641", "642", "643", "644", "645", "646", "647", "648",
         | 
| 424 | 
            +
               "649", "650", "651", "652", "653", "654", "655", "656", "657", "658", "659",
         | 
| 425 | 
            +
               "660", "661", "662", "663", "664", "665", "666", "667", "668", "669", "670",
         | 
| 426 | 
            +
               "671", "672", "673", "674", "675", "676", "677", "678", "679", "680", "681",
         | 
| 427 | 
            +
               "682", "683", "684", "685", "686", "687", "688", "689", "690", "691", "692",
         | 
| 428 | 
            +
               "693", "694", "695", "696", "697", "698", "699", "700", "701", "702", "703",
         | 
| 429 | 
            +
               "704", "705", "706", "707", "708", "709", "710", "711", "712", "713", "714",
         | 
| 430 | 
            +
               "715", "716", "717", "718", "719", "720", "721", "722", "723", "724", "725",
         | 
| 431 | 
            +
               "726", "727", "728", "729", "730", "731", "732", "733", "734", "735", "736",
         | 
| 432 | 
            +
               "737", "738", "739", "740", "741", "742", "743", "744", "745", "746", "747",
         | 
| 433 | 
            +
               "748", "749", "750", "751", "752", "753", "754", "755", "756", "757", "758",
         | 
| 434 | 
            +
               "759", "760", "761", "762", "763", "764", "765", "766", "767", "768", "769",
         | 
| 435 | 
            +
               "770", "771", "772", "773", "774", "775", "776", "777", "778", "779", "780",
         | 
| 436 | 
            +
               "781", "782", "783", "784", "785", "786", "787", "788", "789", "790", "791",
         | 
| 437 | 
            +
               "792", "793", "794", "795", "796", "797", "798", "799", "800", "801", "802",
         | 
| 438 | 
            +
               "803", "804", "805", "806", "807", "808", "809", "810", "811", "812", "813",
         | 
| 439 | 
            +
               "814", "815", "816", "817", "818", "819", "820", "821", "822", "823", "824",
         | 
| 440 | 
            +
               "825", "826", "827", "828", "829", "830", "831", "832", "833", "834", "835",
         | 
| 441 | 
            +
               "836", "837", "838", "839", "840", "841", "842", "843", "844", "845", "846",
         | 
| 442 | 
            +
               "847", "848", "849", "850", "851", "852", "853", "854", "855", "856", "857",
         | 
| 443 | 
            +
               "858", "859", "860", "861", "862", "863", "864", "865", "866", "867", "868",
         | 
| 444 | 
            +
               "869", "870", "871", "872", "873", "874", "875", "876", "877", "878", "879",
         | 
| 445 | 
            +
               "880", "881", "882", "883", "884", "885", "886", "887", "888", "889", "890",
         | 
| 446 | 
            +
               "891", "892", "893", "894", "895", "896", "897", "898", "899", "900", "901",
         | 
| 447 | 
            +
               "902", "903", "904", "905", "906", "907", "908", "909", "910", "911", "912",
         | 
| 448 | 
            +
               "913", "914", "915", "916", "917", "918", "919", "920", "921", "922", "923",
         | 
| 449 | 
            +
               "924", "925", "926", "927", "928", "929", "930", "931", "932", "933", "934",
         | 
| 450 | 
            +
               "935", "936", "937", "938", "939", "940", "941", "942", "943", "944", "945",
         | 
| 451 | 
            +
               "946", "947", "948", "949", "950", "951", "952", "953", "954", "955", "956",
         | 
| 452 | 
            +
               "957", "958", "959", "960", "961", "962", "963", "964", "965", "966", "967",
         | 
| 453 | 
            +
               "968", "969", "970", "971", "972", "973", "974", "975", "976", "977", "978",
         | 
| 454 | 
            +
               "979", "980", "981", "982", "983", "984", "985", "986", "987", "988", "989",
         | 
| 455 | 
            +
               "990", "991", "992", "993", "994", "995", "996", "997", "998", "999"};
         | 
| 456 | 
            +
             | 
| 457 | 
            +
            /**
         | 
| 458 | 
            +
             * Writes an array index to the byte buffer.
         | 
| 459 | 
            +
             */
         | 
| 460 | 
            +
            void pvt_put_array_index(byte_buffer_t *b, int32_t index)
         | 
| 461 | 
            +
            {
         | 
| 462 | 
            +
              char buffer[16];
         | 
| 463 | 
            +
              const char *c_str = NULL;
         | 
| 464 | 
            +
             | 
| 465 | 
            +
              if (index < 1000) {
         | 
| 466 | 
            +
                c_str = index_strings[index];
         | 
| 467 | 
            +
              } else {
         | 
| 468 | 
            +
                c_str = buffer;
         | 
| 469 | 
            +
                snprintf(buffer, sizeof(buffer), "%d", index);
         | 
| 470 | 
            +
              }
         | 
| 471 | 
            +
              size_t length = strlen(c_str) + 1;
         | 
| 472 | 
            +
              ENSURE_BSON_WRITE(b, length);
         | 
| 473 | 
            +
              memcpy(WRITE_PTR(b), c_str, length);
         | 
| 474 | 
            +
              b->write_position += length;
         | 
| 475 | 
            +
            }
         | 
| 476 | 
            +
             | 
| 477 | 
            +
            /**
         | 
| 478 | 
            +
             * serializes an array into the byte buffer
         | 
| 479 | 
            +
             */
         | 
| 480 | 
            +
            VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_keys){
         | 
| 481 | 
            +
              byte_buffer_t *b = NULL;
         | 
| 482 | 
            +
              size_t new_position = 0;
         | 
| 483 | 
            +
              int32_t new_length = 0;
         | 
| 484 | 
            +
              size_t position = 0;
         | 
| 485 | 
            +
              VALUE *array_element = NULL;
         | 
| 486 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 487 | 
            +
              Check_Type(array, T_ARRAY);
         | 
| 488 | 
            +
             | 
| 489 | 
            +
              position = READ_SIZE(b);
         | 
| 490 | 
            +
              /* insert length placeholder */
         | 
| 491 | 
            +
              pvt_put_int32(b, 0);
         | 
| 492 | 
            +
             | 
| 493 | 
            +
              array_element = RARRAY_PTR(array);
         | 
| 494 | 
            +
             | 
| 495 | 
            +
              for(int32_t index=0; index < RARRAY_LEN(array); index++, array_element++){
         | 
| 496 | 
            +
                pvt_put_type_byte(b, *array_element);
         | 
| 497 | 
            +
                pvt_put_array_index(b,index);
         | 
| 498 | 
            +
                pvt_put_field(b, self, *array_element, validating_keys);
         | 
| 499 | 
            +
              }
         | 
| 500 | 
            +
              pvt_put_byte(b, 0);
         | 
| 501 | 
            +
             | 
| 502 | 
            +
              /* update length placeholder */
         | 
| 503 | 
            +
              new_position = READ_SIZE(b);
         | 
| 504 | 
            +
              new_length = new_position - position;
         | 
| 505 | 
            +
              pvt_replace_int32(b, position, new_length);
         | 
| 506 | 
            +
             | 
| 507 | 
            +
              return self;
         | 
| 508 | 
            +
            }
         | 
| 509 | 
            +
             | 
| 183 510 | 
             
            /**
         | 
| 184 511 | 
             
             * Get the length of the buffer.
         | 
| 185 512 | 
             
             */
         | 
| @@ -205,6 +532,13 @@ VALUE rb_bson_byte_buffer_get_byte(VALUE self) | |
| 205 532 | 
             
              return byte;
         | 
| 206 533 | 
             
            }
         | 
| 207 534 |  | 
| 535 | 
            +
            uint8_t pvt_get_type_byte(byte_buffer_t *b){
         | 
| 536 | 
            +
              ENSURE_BSON_READ(b, 1);
         | 
| 537 | 
            +
              int8_t byte = *READ_PTR(b);
         | 
| 538 | 
            +
              b->read_position += 1;
         | 
| 539 | 
            +
              return (uint8_t)byte;
         | 
| 540 | 
            +
            }
         | 
| 541 | 
            +
             | 
| 208 542 | 
             
            /**
         | 
| 209 543 | 
             
             * Get bytes from the buffer.
         | 
| 210 544 | 
             
             */
         | 
| @@ -221,6 +555,14 @@ VALUE rb_bson_byte_buffer_get_bytes(VALUE self, VALUE i) | |
| 221 555 | 
             
              return bytes;
         | 
| 222 556 | 
             
            }
         | 
| 223 557 |  | 
| 558 | 
            +
            VALUE pvt_get_boolean(byte_buffer_t *b){
         | 
| 559 | 
            +
              VALUE result = Qnil;
         | 
| 560 | 
            +
              ENSURE_BSON_READ(b, 1);
         | 
| 561 | 
            +
              result = *READ_PTR(b) == 1 ? Qtrue: Qfalse;
         | 
| 562 | 
            +
              b->read_position += 1;
         | 
| 563 | 
            +
              return result;
         | 
| 564 | 
            +
            }
         | 
| 565 | 
            +
             | 
| 224 566 | 
             
            /**
         | 
| 225 567 | 
             
             * Get a cstring from the buffer.
         | 
| 226 568 | 
             
             */
         | 
| @@ -238,6 +580,17 @@ VALUE rb_bson_byte_buffer_get_cstring(VALUE self) | |
| 238 580 | 
             
              return string;
         | 
| 239 581 | 
             
            }
         | 
| 240 582 |  | 
| 583 | 
            +
            /**
         | 
| 584 | 
            +
             * Reads but does not return a cstring from the buffer.
         | 
| 585 | 
            +
             */
         | 
| 586 | 
            +
            void pvt_skip_cstring(byte_buffer_t *b)
         | 
| 587 | 
            +
            {
         | 
| 588 | 
            +
              int length;
         | 
| 589 | 
            +
              length = (int)strlen(READ_PTR(b));
         | 
| 590 | 
            +
              ENSURE_BSON_READ(b, length);
         | 
| 591 | 
            +
              b->read_position += length + 1;
         | 
| 592 | 
            +
            }
         | 
| 593 | 
            +
             | 
| 241 594 | 
             
            /**
         | 
| 242 595 | 
             
             * Get the 16 bytes representing the decimal128 from the buffer.
         | 
| 243 596 | 
             
             */
         | 
| @@ -259,9 +612,15 @@ VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self) | |
| 259 612 | 
             
            VALUE rb_bson_byte_buffer_get_double(VALUE self)
         | 
| 260 613 | 
             
            {
         | 
| 261 614 | 
             
              byte_buffer_t *b;
         | 
| 262 | 
            -
              double d;
         | 
| 263 615 |  | 
| 264 616 | 
             
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 617 | 
            +
              return pvt_get_double(b);
         | 
| 618 | 
            +
            }
         | 
| 619 | 
            +
             | 
| 620 | 
            +
            VALUE pvt_get_double(byte_buffer_t *b)
         | 
| 621 | 
            +
            {
         | 
| 622 | 
            +
              double d;
         | 
| 623 | 
            +
             | 
| 265 624 | 
             
              ENSURE_BSON_READ(b, 8);
         | 
| 266 625 | 
             
              memcpy(&d, READ_PTR(b), 8);
         | 
| 267 626 | 
             
              b->read_position += 8;
         | 
| @@ -274,9 +633,15 @@ VALUE rb_bson_byte_buffer_get_double(VALUE self) | |
| 274 633 | 
             
            VALUE rb_bson_byte_buffer_get_int32(VALUE self)
         | 
| 275 634 | 
             
            {
         | 
| 276 635 | 
             
              byte_buffer_t *b;
         | 
| 277 | 
            -
              int32_t i32;
         | 
| 278 636 |  | 
| 279 637 | 
             
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 638 | 
            +
              return pvt_get_int32(b);
         | 
| 639 | 
            +
            }
         | 
| 640 | 
            +
             | 
| 641 | 
            +
            VALUE pvt_get_int32(byte_buffer_t *b)
         | 
| 642 | 
            +
            {
         | 
| 643 | 
            +
              int32_t i32;
         | 
| 644 | 
            +
             | 
| 280 645 | 
             
              ENSURE_BSON_READ(b, 4);
         | 
| 281 646 | 
             
              memcpy(&i32, READ_PTR(b), 4);
         | 
| 282 647 | 
             
              b->read_position += 4;
         | 
| @@ -289,9 +654,14 @@ VALUE rb_bson_byte_buffer_get_int32(VALUE self) | |
| 289 654 | 
             
            VALUE rb_bson_byte_buffer_get_int64(VALUE self)
         | 
| 290 655 | 
             
            {
         | 
| 291 656 | 
             
              byte_buffer_t *b;
         | 
| 657 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 658 | 
            +
              return pvt_get_int64(b);
         | 
| 659 | 
            +
            }
         | 
| 660 | 
            +
             | 
| 661 | 
            +
            VALUE pvt_get_int64(byte_buffer_t *b)
         | 
| 662 | 
            +
            {
         | 
| 292 663 | 
             
              int64_t i64;
         | 
| 293 664 |  | 
| 294 | 
            -
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 295 665 | 
             
              ENSURE_BSON_READ(b, 8);
         | 
| 296 666 | 
             
              memcpy(&i64, READ_PTR(b), 8);
         | 
| 297 667 | 
             
              b->read_position += 8;
         | 
| @@ -304,11 +674,17 @@ VALUE rb_bson_byte_buffer_get_int64(VALUE self) | |
| 304 674 | 
             
            VALUE rb_bson_byte_buffer_get_string(VALUE self)
         | 
| 305 675 | 
             
            {
         | 
| 306 676 | 
             
              byte_buffer_t *b;
         | 
| 677 | 
            +
             | 
| 678 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 679 | 
            +
              return pvt_get_string(b);
         | 
| 680 | 
            +
            }
         | 
| 681 | 
            +
             | 
| 682 | 
            +
            VALUE pvt_get_string(byte_buffer_t *b)
         | 
| 683 | 
            +
            {
         | 
| 307 684 | 
             
              int32_t length;
         | 
| 308 685 | 
             
              int32_t length_le;
         | 
| 309 686 | 
             
              VALUE string;
         | 
| 310 687 |  | 
| 311 | 
            -
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 312 688 | 
             
              ENSURE_BSON_READ(b, 4);
         | 
| 313 689 | 
             
              memcpy(&length, READ_PTR(b), 4);
         | 
| 314 690 | 
             
              length_le = BSON_UINT32_FROM_LE(length);
         | 
| @@ -319,6 +695,64 @@ VALUE rb_bson_byte_buffer_get_string(VALUE self) | |
| 319 695 | 
             
              return string;
         | 
| 320 696 | 
             
            }
         | 
| 321 697 |  | 
| 698 | 
            +
             | 
| 699 | 
            +
            VALUE rb_bson_byte_buffer_get_hash(VALUE self){
         | 
| 700 | 
            +
              VALUE doc = Qnil;
         | 
| 701 | 
            +
              byte_buffer_t *b=NULL;
         | 
| 702 | 
            +
              uint8_t type;
         | 
| 703 | 
            +
              VALUE cDocument = rb_const_get(rb_const_get(rb_cObject, rb_intern("BSON")), rb_intern("Document"));
         | 
| 704 | 
            +
             | 
| 705 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 706 | 
            +
             | 
| 707 | 
            +
              pvt_validate_length(b);
         | 
| 708 | 
            +
             | 
| 709 | 
            +
              doc = rb_funcall(cDocument, rb_intern("allocate"),0);
         | 
| 710 | 
            +
             | 
| 711 | 
            +
              while((type = pvt_get_type_byte(b)) != 0){
         | 
| 712 | 
            +
                VALUE field = rb_bson_byte_buffer_get_cstring(self);
         | 
| 713 | 
            +
                rb_hash_aset(doc, field, pvt_read_field(b, self, type));
         | 
| 714 | 
            +
              }
         | 
| 715 | 
            +
              return doc;
         | 
| 716 | 
            +
            }
         | 
| 717 | 
            +
             | 
| 718 | 
            +
            VALUE rb_bson_byte_buffer_get_array(VALUE self){
         | 
| 719 | 
            +
              byte_buffer_t *b;
         | 
| 720 | 
            +
              VALUE array = Qnil;
         | 
| 721 | 
            +
              uint8_t type;
         | 
| 722 | 
            +
             | 
| 723 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 724 | 
            +
             | 
| 725 | 
            +
              pvt_validate_length(b);
         | 
| 726 | 
            +
             | 
| 727 | 
            +
              array = rb_ary_new();
         | 
| 728 | 
            +
              while((type = pvt_get_type_byte(b)) != 0){
         | 
| 729 | 
            +
                pvt_skip_cstring(b);
         | 
| 730 | 
            +
                rb_ary_push(array,  pvt_read_field(b, self, type));
         | 
| 731 | 
            +
              }
         | 
| 732 | 
            +
              return array;
         | 
| 733 | 
            +
            }
         | 
| 734 | 
            +
             | 
| 735 | 
            +
            /**
         | 
| 736 | 
            +
             * Read a single field from a hash or array
         | 
| 737 | 
            +
             */
         | 
| 738 | 
            +
            VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type){
         | 
| 739 | 
            +
              switch(type) {
         | 
| 740 | 
            +
                case BSON_TYPE_INT32: return pvt_get_int32(b);
         | 
| 741 | 
            +
                case BSON_TYPE_INT64: return pvt_get_int64(b);
         | 
| 742 | 
            +
                case BSON_TYPE_DOUBLE: return pvt_get_double(b);
         | 
| 743 | 
            +
                case BSON_TYPE_STRING: return pvt_get_string(b);
         | 
| 744 | 
            +
                case BSON_TYPE_ARRAY: return rb_bson_byte_buffer_get_array(rb_buffer);
         | 
| 745 | 
            +
                case BSON_TYPE_OBJECT: return rb_bson_byte_buffer_get_hash(rb_buffer);
         | 
| 746 | 
            +
                case BSON_TYPE_BOOLEAN: return pvt_get_boolean(b);
         | 
| 747 | 
            +
                default:
         | 
| 748 | 
            +
                {
         | 
| 749 | 
            +
                  VALUE klass = rb_funcall(rb_bson_registry,rb_intern("get"),1, INT2FIX(type));
         | 
| 750 | 
            +
                  VALUE value = rb_funcall(klass, rb_intern("from_bson"),1, rb_buffer);
         | 
| 751 | 
            +
                  return value;
         | 
| 752 | 
            +
                }
         | 
| 753 | 
            +
              }
         | 
| 754 | 
            +
            }
         | 
| 755 | 
            +
             | 
| 322 756 | 
             
            /**
         | 
| 323 757 | 
             
             * Writes a byte to the byte buffer.
         | 
| 324 758 | 
             
             */
         | 
| @@ -335,6 +769,13 @@ VALUE rb_bson_byte_buffer_put_byte(VALUE self, VALUE byte) | |
| 335 769 | 
             
              return self;
         | 
| 336 770 | 
             
            }
         | 
| 337 771 |  | 
| 772 | 
            +
            void pvt_put_byte( byte_buffer_t *b, const char byte)
         | 
| 773 | 
            +
            {
         | 
| 774 | 
            +
              ENSURE_BSON_WRITE(b, 1);
         | 
| 775 | 
            +
              *WRITE_PTR(b) = byte;
         | 
| 776 | 
            +
              b->write_position += 1;
         | 
| 777 | 
            +
             | 
| 778 | 
            +
            }
         | 
| 338 779 | 
             
            /**
         | 
| 339 780 | 
             
             * Writes bytes to the byte buffer.
         | 
| 340 781 | 
             
             */
         | 
| @@ -357,18 +798,37 @@ VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes) | |
| 357 798 | 
             
            VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string)
         | 
| 358 799 | 
             
            {
         | 
| 359 800 | 
             
              byte_buffer_t *b;
         | 
| 801 | 
            +
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 802 | 
            +
              pvt_put_cstring(b, string);
         | 
| 803 | 
            +
              return self;
         | 
| 804 | 
            +
            }
         | 
| 805 | 
            +
             | 
| 806 | 
            +
            void pvt_put_cstring(byte_buffer_t *b, VALUE string)
         | 
| 807 | 
            +
            {
         | 
| 360 808 | 
             
              char *c_str = RSTRING_PTR(string);
         | 
| 361 809 | 
             
              size_t length = RSTRING_LEN(string) + 1;
         | 
| 362 810 |  | 
| 363 811 | 
             
              if (!rb_bson_utf8_validate(c_str, length - 1, false)) {
         | 
| 364 812 | 
             
                rb_raise(rb_eArgError, "String %s is not a valid UTF-8 CString.", c_str);
         | 
| 365 813 | 
             
              }
         | 
| 366 | 
            -
             | 
| 367 | 
            -
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 368 814 | 
             
              ENSURE_BSON_WRITE(b, length);
         | 
| 369 815 | 
             
              memcpy(WRITE_PTR(b), c_str, length);
         | 
| 370 816 | 
             
              b->write_position += length;
         | 
| 371 | 
            -
             | 
| 817 | 
            +
            }
         | 
| 818 | 
            +
             | 
| 819 | 
            +
            /**
         | 
| 820 | 
            +
             * Write a hash key to the byte buffer, validating it if requested
         | 
| 821 | 
            +
             */
         | 
| 822 | 
            +
            void pvt_put_bson_key(byte_buffer_t *b, VALUE string, VALUE validating_keys){
         | 
| 823 | 
            +
              if(RTEST(validating_keys)){
         | 
| 824 | 
            +
                char *c_str = RSTRING_PTR(string);
         | 
| 825 | 
            +
                size_t length = RSTRING_LEN(string);
         | 
| 826 | 
            +
                if(length > 0 && (c_str[0] == '$' || memchr(c_str, '.', length))){
         | 
| 827 | 
            +
                  rb_exc_raise(rb_funcall(rb_bson_illegal_key, rb_intern("new"),1, string));
         | 
| 828 | 
            +
                }
         | 
| 829 | 
            +
              }
         | 
| 830 | 
            +
             | 
| 831 | 
            +
              pvt_put_cstring(b, string);
         | 
| 372 832 | 
             
            }
         | 
| 373 833 |  | 
| 374 834 | 
             
            /**
         | 
| @@ -398,13 +858,18 @@ VALUE rb_bson_byte_buffer_put_decimal128(VALUE self, VALUE low, VALUE high) | |
| 398 858 | 
             
            VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f)
         | 
| 399 859 | 
             
            {
         | 
| 400 860 | 
             
              byte_buffer_t *b;
         | 
| 401 | 
            -
              const double d = BSON_DOUBLE_TO_LE(NUM2DBL(f));
         | 
| 402 861 | 
             
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 862 | 
            +
              pvt_put_double(b,NUM2DBL(f));
         | 
| 863 | 
            +
             | 
| 864 | 
            +
              return self;
         | 
| 865 | 
            +
            }
         | 
| 866 | 
            +
             | 
| 867 | 
            +
            void pvt_put_double(byte_buffer_t *b, double f)
         | 
| 868 | 
            +
            {
         | 
| 869 | 
            +
              const double d = BSON_DOUBLE_TO_LE(f);
         | 
| 403 870 | 
             
              ENSURE_BSON_WRITE(b, 8);
         | 
| 404 871 | 
             
              memcpy(WRITE_PTR(b), &d, 8);
         | 
| 405 872 | 
             
              b->write_position += 8;
         | 
| 406 | 
            -
             | 
| 407 | 
            -
              return self;
         | 
| 408 873 | 
             
            }
         | 
| 409 874 |  | 
| 410 875 | 
             
            /**
         | 
| @@ -413,14 +878,19 @@ VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f) | |
| 413 878 | 
             
            VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i)
         | 
| 414 879 | 
             
            {
         | 
| 415 880 | 
             
              byte_buffer_t *b;
         | 
| 416 | 
            -
              const int32_t i32 =  | 
| 881 | 
            +
              const int32_t i32 = NUM2INT(i);
         | 
| 417 882 |  | 
| 418 883 | 
             
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 884 | 
            +
              pvt_put_int32(b, i32);
         | 
| 885 | 
            +
              return self;
         | 
| 886 | 
            +
            }
         | 
| 887 | 
            +
             | 
| 888 | 
            +
            void pvt_put_int32(byte_buffer_t *b, const int32_t i)
         | 
| 889 | 
            +
            {
         | 
| 890 | 
            +
              const int32_t i32 = BSON_UINT32_TO_LE(i);
         | 
| 419 891 | 
             
              ENSURE_BSON_WRITE(b, 4);
         | 
| 420 892 | 
             
              memcpy(WRITE_PTR(b), &i32, 4);
         | 
| 421 893 | 
             
              b->write_position += 4;
         | 
| 422 | 
            -
             | 
| 423 | 
            -
              return self;
         | 
| 424 894 | 
             
            }
         | 
| 425 895 |  | 
| 426 896 | 
             
            /**
         | 
| @@ -429,14 +899,49 @@ VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i) | |
| 429 899 | 
             
            VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i)
         | 
| 430 900 | 
             
            {
         | 
| 431 901 | 
             
              byte_buffer_t *b;
         | 
| 432 | 
            -
              const int64_t i64 =  | 
| 902 | 
            +
              const int64_t i64 = NUM2LL(i);
         | 
| 433 903 |  | 
| 434 904 | 
             
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 905 | 
            +
              pvt_put_int64(b, i64);
         | 
| 906 | 
            +
             | 
| 907 | 
            +
              return self;
         | 
| 908 | 
            +
            }
         | 
| 909 | 
            +
             | 
| 910 | 
            +
            void pvt_put_int64(byte_buffer_t *b, const int64_t i)
         | 
| 911 | 
            +
            {
         | 
| 912 | 
            +
              const int64_t i64 = BSON_UINT64_TO_LE(i);
         | 
| 913 | 
            +
             | 
| 435 914 | 
             
              ENSURE_BSON_WRITE(b, 8);
         | 
| 436 915 | 
             
              memcpy(WRITE_PTR(b), &i64, 8);
         | 
| 437 916 | 
             
              b->write_position += 8;
         | 
| 438 917 |  | 
| 439 | 
            -
             | 
| 918 | 
            +
            }
         | 
| 919 | 
            +
             | 
| 920 | 
            +
            /**
         | 
| 921 | 
            +
             * validate the buffer contains the amount of bytes the array / hash claimns
         | 
| 922 | 
            +
             * and that it is null terminated
         | 
| 923 | 
            +
             */
         | 
| 924 | 
            +
            void pvt_validate_length(byte_buffer_t *b)
         | 
| 925 | 
            +
            {
         | 
| 926 | 
            +
              int32_t length;
         | 
| 927 | 
            +
              
         | 
| 928 | 
            +
              ENSURE_BSON_READ(b, 4);
         | 
| 929 | 
            +
              memcpy(&length, READ_PTR(b), 4);
         | 
| 930 | 
            +
              length = BSON_UINT32_TO_LE(length);
         | 
| 931 | 
            +
             | 
| 932 | 
            +
              /* minimum valid length is 4 (byte count) + 1 (terminating byte) */ 
         | 
| 933 | 
            +
              if(length >= 5){
         | 
| 934 | 
            +
                ENSURE_BSON_READ(b, length);
         | 
| 935 | 
            +
             | 
| 936 | 
            +
                /* The last byte should be a null byte: it should be at length - 1 */
         | 
| 937 | 
            +
                if( *(READ_PTR(b) + length - 1) != 0 ){
         | 
| 938 | 
            +
                  rb_raise(rb_eRangeError, "Buffer should have contained null terminator at %zu but contained %d", b->read_position + (size_t)length, (int)*(READ_PTR(b) + length));
         | 
| 939 | 
            +
                }
         | 
| 940 | 
            +
                b->read_position += 4;
         | 
| 941 | 
            +
              }
         | 
| 942 | 
            +
              else{
         | 
| 943 | 
            +
                rb_raise(rb_eRangeError, "Buffer contained invalid length %d at %zu", length, b->read_position);
         | 
| 944 | 
            +
              }
         | 
| 440 945 | 
             
            }
         | 
| 441 946 |  | 
| 442 947 | 
             
            /**
         | 
| @@ -481,16 +986,19 @@ VALUE rb_bson_byte_buffer_read_position(VALUE self) | |
| 481 986 | 
             
            VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i)
         | 
| 482 987 | 
             
            {
         | 
| 483 988 | 
             
              byte_buffer_t *b;
         | 
| 484 | 
            -
              const int32_t position = NUM2LONG(index);
         | 
| 485 | 
            -
              const int32_t i32 = BSON_UINT32_TO_LE(NUM2LONG(i));
         | 
| 486 989 |  | 
| 487 990 | 
             
              TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
         | 
| 488 | 
            -
             | 
| 489 | 
            -
              memcpy(READ_PTR(b) + position, &i32, 4);
         | 
| 991 | 
            +
              pvt_replace_int32(b, NUM2LONG(index), NUM2LONG(i));
         | 
| 490 992 |  | 
| 491 993 | 
             
              return self;
         | 
| 492 994 | 
             
            }
         | 
| 493 995 |  | 
| 996 | 
            +
            void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval)
         | 
| 997 | 
            +
            {
         | 
| 998 | 
            +
              const int32_t i32 = BSON_UINT32_TO_LE(newval);
         | 
| 999 | 
            +
              memcpy(READ_PTR(b) + position, &i32, 4);
         | 
| 1000 | 
            +
            }
         | 
| 1001 | 
            +
             | 
| 494 1002 | 
             
            /**
         | 
| 495 1003 | 
             
             * Reset the read position to the beginning of the byte buffer.
         | 
| 496 1004 | 
             
             */
         | 
    
        data/lib/bson/array.rb
    CHANGED
    
    | @@ -41,15 +41,19 @@ module BSON | |
| 41 41 | 
             
                #
         | 
| 42 42 | 
             
                # @since 2.0.0
         | 
| 43 43 | 
             
                def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
         | 
| 44 | 
            -
                   | 
| 45 | 
            -
             | 
| 46 | 
            -
                   | 
| 47 | 
            -
                    buffer. | 
| 48 | 
            -
                    buffer. | 
| 49 | 
            -
                    value | 
| 44 | 
            +
                  if buffer.respond_to?(:put_array)
         | 
| 45 | 
            +
                    buffer.put_array(self, validating_keys)
         | 
| 46 | 
            +
                  else
         | 
| 47 | 
            +
                    position = buffer.length
         | 
| 48 | 
            +
                    buffer.put_int32(0)
         | 
| 49 | 
            +
                    each_with_index do |value, index|
         | 
| 50 | 
            +
                      buffer.put_byte(value.bson_type)
         | 
| 51 | 
            +
                      buffer.put_cstring(index.to_s)
         | 
| 52 | 
            +
                      value.to_bson(buffer, validating_keys)
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                    buffer.put_byte(NULL_BYTE)
         | 
| 55 | 
            +
                    buffer.replace_int32(position, buffer.length - position)
         | 
| 50 56 | 
             
                  end
         | 
| 51 | 
            -
                  buffer.put_byte(NULL_BYTE)
         | 
| 52 | 
            -
                  buffer.replace_int32(position, buffer.length - position)
         | 
| 53 57 | 
             
                end
         | 
| 54 58 |  | 
| 55 59 | 
             
                # Convert the array to an object id. This will only work for arrays of size
         | 
| @@ -93,13 +97,17 @@ module BSON | |
| 93 97 | 
             
                  #
         | 
| 94 98 | 
             
                  # @since 2.0.0
         | 
| 95 99 | 
             
                  def from_bson(buffer)
         | 
| 96 | 
            -
                     | 
| 97 | 
            -
             | 
| 98 | 
            -
                     | 
| 99 | 
            -
                       | 
| 100 | 
            -
                       | 
| 100 | 
            +
                    if buffer.respond_to?(:get_array)
         | 
| 101 | 
            +
                      buffer.get_array
         | 
| 102 | 
            +
                    else
         | 
| 103 | 
            +
                      array = new
         | 
| 104 | 
            +
                      buffer.get_int32 # throw away the length
         | 
| 105 | 
            +
                      while (type = buffer.get_byte) != NULL_BYTE
         | 
| 106 | 
            +
                        buffer.get_cstring
         | 
| 107 | 
            +
                        array << BSON::Registry.get(type).from_bson(buffer)
         | 
| 108 | 
            +
                      end
         | 
| 109 | 
            +
                      array
         | 
| 101 110 | 
             
                    end
         | 
| 102 | 
            -
                    array
         | 
| 103 111 | 
             
                  end
         | 
| 104 112 | 
             
                end
         | 
| 105 113 |  | 
    
        data/lib/bson/hash.rb
    CHANGED
    
    | @@ -38,15 +38,19 @@ module BSON | |
| 38 38 | 
             
                #
         | 
| 39 39 | 
             
                # @since 2.0.0
         | 
| 40 40 | 
             
                def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
         | 
| 41 | 
            -
                   | 
| 42 | 
            -
             | 
| 43 | 
            -
                   | 
| 44 | 
            -
                    buffer. | 
| 45 | 
            -
                    buffer. | 
| 46 | 
            -
                     | 
| 41 | 
            +
                  if buffer.respond_to?(:put_hash)
         | 
| 42 | 
            +
                    buffer.put_hash(self, validating_keys)
         | 
| 43 | 
            +
                  else
         | 
| 44 | 
            +
                    position = buffer.length
         | 
| 45 | 
            +
                    buffer.put_int32(0)
         | 
| 46 | 
            +
                    each do |field, value|
         | 
| 47 | 
            +
                      buffer.put_byte(value.bson_type)
         | 
| 48 | 
            +
                      buffer.put_cstring(field.to_bson_key(validating_keys))
         | 
| 49 | 
            +
                      value.to_bson(buffer, validating_keys)
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                    buffer.put_byte(NULL_BYTE)
         | 
| 52 | 
            +
                    buffer.replace_int32(position, buffer.length - position)
         | 
| 47 53 | 
             
                  end
         | 
| 48 | 
            -
                  buffer.put_byte(NULL_BYTE)
         | 
| 49 | 
            -
                  buffer.replace_int32(position, buffer.length - position)
         | 
| 50 54 | 
             
                end
         | 
| 51 55 |  | 
| 52 56 | 
             
                # Converts the hash to a normalized value in a BSON document.
         | 
| @@ -73,13 +77,17 @@ module BSON | |
| 73 77 | 
             
                  #
         | 
| 74 78 | 
             
                  # @since 2.0.0
         | 
| 75 79 | 
             
                  def from_bson(buffer)
         | 
| 76 | 
            -
                     | 
| 77 | 
            -
             | 
| 78 | 
            -
                     | 
| 79 | 
            -
                       | 
| 80 | 
            -
                       | 
| 80 | 
            +
                    if buffer.respond_to?(:get_hash)
         | 
| 81 | 
            +
                      buffer.get_hash
         | 
| 82 | 
            +
                    else
         | 
| 83 | 
            +
                      hash = Document.allocate
         | 
| 84 | 
            +
                      buffer.get_int32 # Throw away the size.
         | 
| 85 | 
            +
                      while (type = buffer.get_byte) != NULL_BYTE
         | 
| 86 | 
            +
                        field = buffer.get_cstring
         | 
| 87 | 
            +
                        hash.store(field, BSON::Registry.get(type, field).from_bson(buffer))
         | 
| 88 | 
            +
                      end
         | 
| 89 | 
            +
                      hash
         | 
| 81 90 | 
             
                    end
         | 
| 82 | 
            -
                    hash
         | 
| 83 91 | 
             
                  end
         | 
| 84 92 | 
             
                end
         | 
| 85 93 |  | 
    
        data/lib/bson/registry.rb
    CHANGED
    
    | @@ -40,7 +40,7 @@ module BSON | |
| 40 40 | 
             
                #
         | 
| 41 41 | 
             
                # @since 2.0.0
         | 
| 42 42 | 
             
                def get(byte, field = nil)
         | 
| 43 | 
            -
                  if type = MAPPINGS[byte]
         | 
| 43 | 
            +
                  if type = MAPPINGS[byte] || (byte.is_a?(String) && type = MAPPINGS[byte.ord])
         | 
| 44 44 | 
             
                    type
         | 
| 45 45 | 
             
                  else
         | 
| 46 46 | 
             
                    handle_unsupported_type!(byte, field)
         | 
| @@ -59,7 +59,7 @@ module BSON | |
| 59 59 | 
             
                #
         | 
| 60 60 | 
             
                # @since 2.0.0
         | 
| 61 61 | 
             
                def register(byte, type)
         | 
| 62 | 
            -
                  MAPPINGS. | 
| 62 | 
            +
                  MAPPINGS[byte.ord] = type
         | 
| 63 63 | 
             
                  define_type_reader(type)
         | 
| 64 64 | 
             
                end
         | 
| 65 65 |  | 
    
        data/lib/bson/symbol.rb
    CHANGED
    
    | @@ -105,7 +105,7 @@ module BSON | |
| 105 105 | 
             
                # Register this type when the module is loaded.
         | 
| 106 106 | 
             
                #
         | 
| 107 107 | 
             
                # @since 2.0.0
         | 
| 108 | 
            -
                Registry::MAPPINGS. | 
| 108 | 
            +
                Registry::MAPPINGS[BSON_TYPE.ord] = ::Symbol
         | 
| 109 109 | 
             
              end
         | 
| 110 110 |  | 
| 111 111 | 
             
              # Enrich the core Symbol class with this module.
         | 
    
        data/lib/bson/timestamp.rb
    CHANGED
    
    | @@ -21,12 +21,18 @@ module BSON | |
| 21 21 | 
             
              # @since 2.0.0
         | 
| 22 22 | 
             
              class Timestamp
         | 
| 23 23 | 
             
                include JSON
         | 
| 24 | 
            +
                include Comparable
         | 
| 24 25 |  | 
| 25 26 | 
             
                # A timestamp is type 0x11 in the BSON spec.
         | 
| 26 27 | 
             
                #
         | 
| 27 28 | 
             
                # @since 2.0.0
         | 
| 28 29 | 
             
                BSON_TYPE = 17.chr.force_encoding(BINARY).freeze
         | 
| 29 30 |  | 
| 31 | 
            +
                # Error message if an object other than a Timestamp is compared with this object.
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # @since 4.3.0
         | 
| 34 | 
            +
                COMPARISON_ERROR_MESSAGE = 'comparison of %s with Timestamp failed'.freeze
         | 
| 35 | 
            +
             | 
| 30 36 | 
             
                # @!attribute seconds
         | 
| 31 37 | 
             
                #   @return [ Integer ] The number of seconds.
         | 
| 32 38 | 
             
                #   @since 2.0.0
         | 
| @@ -52,6 +58,24 @@ module BSON | |
| 52 58 | 
             
                  seconds == other.seconds && increment == other.increment
         | 
| 53 59 | 
             
                end
         | 
| 54 60 |  | 
| 61 | 
            +
                # Determine if this timestamp is greater or less than another object.
         | 
| 62 | 
            +
                #
         | 
| 63 | 
            +
                # @example Compare the timestamp.
         | 
| 64 | 
            +
                #   timestamp < other
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                # @param [ Object ] other The object to compare against.
         | 
| 67 | 
            +
                #
         | 
| 68 | 
            +
                # @return [ true, false ] The result of the comparison.
         | 
| 69 | 
            +
                #
         | 
| 70 | 
            +
                # @since 4.3.0
         | 
| 71 | 
            +
                def <=>(other)
         | 
| 72 | 
            +
                  raise ArgumentError.new(COMPARISON_ERROR_MESSAGE % other.class) unless other.is_a?(Timestamp)
         | 
| 73 | 
            +
                  return 0 if self == other
         | 
| 74 | 
            +
                  a = [ seconds, increment ]
         | 
| 75 | 
            +
                  b = [ other.seconds, other.increment ]
         | 
| 76 | 
            +
                  [ a, b ].sort[0] == a ? -1 : 1
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 55 79 | 
             
                # Get the timestamp as JSON hash data.
         | 
| 56 80 | 
             
                #
         | 
| 57 81 | 
             
                # @example Get the timestamp as a JSON hash.
         | 
    
        data/lib/bson/version.rb
    CHANGED
    
    
| @@ -152,16 +152,30 @@ describe BSON::ByteBuffer do | |
| 152 152 |  | 
| 153 153 | 
             
              describe '#length' do
         | 
| 154 154 |  | 
| 155 | 
            -
                 | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 155 | 
            +
                context 'when the byte buffer is initialized with no bytes' do
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  let(:buffer) do
         | 
| 158 | 
            +
                    described_class.new
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                  before do
         | 
| 162 | 
            +
                    buffer.put_int32(5)
         | 
| 163 | 
            +
                  end
         | 
| 158 164 |  | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 165 | 
            +
                  it 'returns the length of the buffer' do
         | 
| 166 | 
            +
                    expect(buffer.length).to eq(4)
         | 
| 167 | 
            +
                  end
         | 
| 161 168 | 
             
                end
         | 
| 162 169 |  | 
| 163 | 
            -
                 | 
| 164 | 
            -
             | 
| 170 | 
            +
                context 'when the byte buffer is initialized with some bytes' do
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                  let(:buffer) do
         | 
| 173 | 
            +
                    described_class.new("#{BSON::Int32::BSON_TYPE}#{BSON::Int32::BSON_TYPE}")
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                  it 'returns the length' do
         | 
| 177 | 
            +
                    expect(buffer.length).to eq(2)
         | 
| 178 | 
            +
                  end
         | 
| 165 179 | 
             
                end
         | 
| 166 180 | 
             
              end
         | 
| 167 181 |  | 
    
        data/spec/bson/document_spec.rb
    CHANGED
    
    | @@ -756,6 +756,24 @@ describe BSON::Document do | |
| 756 756 | 
             
                  end
         | 
| 757 757 | 
             
                end
         | 
| 758 758 |  | 
| 759 | 
            +
                context "when the hash contains an array of hashes" do
         | 
| 760 | 
            +
                  let(:obj) do
         | 
| 761 | 
            +
                    described_class["key",[{"a" => 1}, {"b" => 2}]]
         | 
| 762 | 
            +
                  end
         | 
| 763 | 
            +
             | 
| 764 | 
            +
                  let(:bson) do
         | 
| 765 | 
            +
                    "#{45.to_bson}#{Array::BSON_TYPE}key#{BSON::NULL_BYTE}" +
         | 
| 766 | 
            +
                    "#{35.to_bson}"+
         | 
| 767 | 
            +
                    "#{BSON::Document::BSON_TYPE}0#{BSON::NULL_BYTE}#{12.to_bson}#{BSON::Int32::BSON_TYPE}a#{BSON::NULL_BYTE}#{1.to_bson}#{BSON::NULL_BYTE}" +
         | 
| 768 | 
            +
                    "#{BSON::Document::BSON_TYPE}1#{BSON::NULL_BYTE}#{12.to_bson}#{BSON::Int32::BSON_TYPE}b#{BSON::NULL_BYTE}#{2.to_bson}#{BSON::NULL_BYTE}" +
         | 
| 769 | 
            +
                    "#{BSON::NULL_BYTE}" + 
         | 
| 770 | 
            +
                    "#{BSON::NULL_BYTE}"
         | 
| 771 | 
            +
                  end
         | 
| 772 | 
            +
             | 
| 773 | 
            +
                  it_behaves_like "a serializable bson element"
         | 
| 774 | 
            +
                  it_behaves_like "a deserializable bson element"
         | 
| 775 | 
            +
                end
         | 
| 776 | 
            +
             | 
| 759 777 | 
             
                context "when the hash is a single level" do
         | 
| 760 778 |  | 
| 761 779 | 
             
                  let(:obj) do
         | 
    
        data/spec/bson/timestamp_spec.rb
    CHANGED
    
    | @@ -48,6 +48,61 @@ describe BSON::Timestamp do | |
| 48 48 | 
             
                end
         | 
| 49 49 | 
             
              end
         | 
| 50 50 |  | 
| 51 | 
            +
              describe "#<=>" do
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                let(:timestamp) do
         | 
| 54 | 
            +
                  described_class.new(1, 10)
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                context "when the objects are equal" do
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  let(:other) { described_class.new(1, 10) }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  it "returns 0" do
         | 
| 62 | 
            +
                    expect(timestamp).to eq(other)
         | 
| 63 | 
            +
                    expect(timestamp < other).to be(false)
         | 
| 64 | 
            +
                    expect(timestamp > other).to be(false)
         | 
| 65 | 
            +
                    expect(timestamp >= other).to be(true)
         | 
| 66 | 
            +
                    expect(timestamp <= other).to be(true)
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                context "when the first object is less than the second" do
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  let(:other) { described_class.new(1, 15) }
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  it "returns -1" do
         | 
| 75 | 
            +
                    expect(timestamp <=> other).to be(-1)
         | 
| 76 | 
            +
                    expect(timestamp < other).to be(true)
         | 
| 77 | 
            +
                    expect(timestamp > other).to be(false)
         | 
| 78 | 
            +
                    expect(timestamp >= other).to be(false)
         | 
| 79 | 
            +
                    expect(timestamp <= other).to be(true)
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                context "when the first object is greater than the second" do
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  let(:other) { described_class.new(1, 5) }
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  it "returns 1" do
         | 
| 88 | 
            +
                    expect(timestamp <=> other).to be(1)
         | 
| 89 | 
            +
                    expect(timestamp < other).to be(false)
         | 
| 90 | 
            +
                    expect(timestamp > other).to be(true)
         | 
| 91 | 
            +
                    expect(timestamp >= other).to be(true)
         | 
| 92 | 
            +
                    expect(timestamp <= other).to be(false)
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                context "when the other object is not a timestamp" do
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  it "raises an ArgumentError" do
         | 
| 99 | 
            +
                    expect {
         | 
| 100 | 
            +
                      timestamp < 1
         | 
| 101 | 
            +
                    }.to raise_exception(ArgumentError)
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
             | 
| 51 106 | 
             
              describe "#as_json" do
         | 
| 52 107 |  | 
| 53 108 | 
             
                let(:object) do
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: bson
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 4. | 
| 4 | 
            +
              version: 4.3.0.beta
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Tyler Brock
         | 
| @@ -34,7 +34,7 @@ cert_chain: | |
| 34 34 | 
             
              UgLdYyyGANc+TOKLFmx0eAJlCljAurbX7ctO2XI0f1AUdEYSqGzut+datXK/9nwQ
         | 
| 35 35 | 
             
              FACf8zd11PEds/Opai2Qp4aOBgaxXhhFG357umy1vRs=
         | 
| 36 36 | 
             
              -----END CERTIFICATE-----
         | 
| 37 | 
            -
            date: 2017- | 
| 37 | 
            +
            date: 2017-09-20 00:00:00.000000000 Z
         | 
| 38 38 | 
             
            dependencies: []
         | 
| 39 39 | 
             
            description: A full featured BSON specification implementation, in Ruby
         | 
| 40 40 | 
             
            email:
         | 
    
        metadata.gz.sig
    CHANGED
    
    | Binary file |