| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 case UPB_TYPE_MESSAGE: return sizeof(VALUE); | 50 case UPB_TYPE_MESSAGE: return sizeof(VALUE); |
| 51 case UPB_TYPE_ENUM: return 4; | 51 case UPB_TYPE_ENUM: return 4; |
| 52 case UPB_TYPE_INT32: return 4; | 52 case UPB_TYPE_INT32: return 4; |
| 53 case UPB_TYPE_INT64: return 8; | 53 case UPB_TYPE_INT64: return 8; |
| 54 case UPB_TYPE_UINT32: return 4; | 54 case UPB_TYPE_UINT32: return 4; |
| 55 case UPB_TYPE_UINT64: return 8; | 55 case UPB_TYPE_UINT64: return 8; |
| 56 default: return 0; | 56 default: return 0; |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 | 59 |
| 60 static VALUE value_from_default(const upb_fielddef *field) { | |
| 61 switch (upb_fielddef_type(field)) { | |
| 62 case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field)); | |
| 63 case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field)); | |
| 64 case UPB_TYPE_BOOL: | |
| 65 return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse; | |
| 66 case UPB_TYPE_MESSAGE: return Qnil; | |
| 67 case UPB_TYPE_ENUM: { | |
| 68 const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field); | |
| 69 int32_t num = upb_fielddef_defaultint32(field); | |
| 70 const char *label = upb_enumdef_iton(enumdef, num); | |
| 71 if (label) { | |
| 72 return ID2SYM(rb_intern(label)); | |
| 73 } else { | |
| 74 return INT2NUM(num); | |
| 75 } | |
| 76 } | |
| 77 case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field)); | |
| 78 case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));; | |
| 79 case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field)); | |
| 80 case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field)); | |
| 81 case UPB_TYPE_STRING: | |
| 82 case UPB_TYPE_BYTES: { | |
| 83 size_t size; | |
| 84 const char *str = upb_fielddef_defaultstr(field, &size); | |
| 85 return rb_str_new(str, size); | |
| 86 } | |
| 87 default: return Qnil; | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 static bool is_ruby_num(VALUE value) { | 60 static bool is_ruby_num(VALUE value) { |
| 92 return (TYPE(value) == T_FLOAT || | 61 return (TYPE(value) == T_FLOAT || |
| 93 TYPE(value) == T_FIXNUM || | 62 TYPE(value) == T_FIXNUM || |
| 94 TYPE(value) == T_BIGNUM); | 63 TYPE(value) == T_BIGNUM); |
| 95 } | 64 } |
| 96 | 65 |
| 97 void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) { | 66 void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) { |
| 98 if (!is_ruby_num(val)) { | 67 if (!is_ruby_num(val)) { |
| 99 rb_raise(rb_eTypeError, "Expected number type for integral field."); | 68 rb_raise(rb_eTypeError, "Expected number type for integral field."); |
| 100 } | 69 } |
| 101 | 70 |
| 102 // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper | 71 // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper |
| 103 // bound; we just need to do precision checks (i.e., disallow rounding) and | 72 // bound; we just need to do precision checks (i.e., disallow rounding) and |
| 104 // check for < 0 on unsigned types. | 73 // check for < 0 on unsigned types. |
| 105 if (TYPE(val) == T_FLOAT) { | 74 if (TYPE(val) == T_FLOAT) { |
| 106 double dbl_val = NUM2DBL(val); | 75 double dbl_val = NUM2DBL(val); |
| 107 if (floor(dbl_val) != dbl_val) { | 76 if (floor(dbl_val) != dbl_val) { |
| 108 rb_raise(rb_eRangeError, | 77 rb_raise(rb_eRangeError, |
| 109 "Non-integral floating point value assigned to integer field."); | 78 "Non-integral floating point value assigned to integer field."); |
| 110 } | 79 } |
| 111 } | 80 } |
| 112 if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) { | 81 if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) { |
| 113 if (NUM2DBL(val) < 0) { | 82 if (NUM2DBL(val) < 0) { |
| 114 rb_raise(rb_eRangeError, | 83 rb_raise(rb_eRangeError, |
| 115 "Assigning negative value to unsigned integer field."); | 84 "Assigning negative value to unsigned integer field."); |
| 116 } | 85 } |
| 117 } | 86 } |
| 118 } | 87 } |
| 119 | 88 |
| 120 VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) { | 89 void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) { |
| 121 rb_encoding* desired_encoding = (type == UPB_TYPE_STRING) ? | 90 bool bad_encoding = false; |
| 122 kRubyStringUtf8Encoding : kRubyString8bitEncoding; | 91 rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value)); |
| 123 VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding); | 92 if (type == UPB_TYPE_STRING) { |
| 124 | 93 bad_encoding = |
| 125 // Note: this will not duplicate underlying string data unless necessary. | 94 string_encoding != kRubyStringUtf8Encoding && |
| 126 value = rb_str_encode(value, desired_encoding_value, 0, Qnil); | 95 string_encoding != kRubyStringASCIIEncoding; |
| 127 | 96 } else { |
| 128 if (type == UPB_TYPE_STRING && | 97 bad_encoding = |
| 129 rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) { | 98 string_encoding != kRubyString8bitEncoding; |
| 130 rb_raise(rb_eEncodingError, "String is invalid UTF-8"); | |
| 131 } | 99 } |
| 132 | 100 // Check that encoding is UTF-8 or ASCII (for string fields) or ASCII-8BIT |
| 133 // Ensure the data remains valid. Since we called #encode a moment ago, | 101 // (for bytes fields). |
| 134 // this does not freeze the string the user assigned. | 102 if (bad_encoding) { |
| 135 rb_obj_freeze(value); | 103 rb_raise(rb_eTypeError, "Encoding for '%s' fields must be %s (was %s)", |
| 136 | 104 (type == UPB_TYPE_STRING) ? "string" : "bytes", |
| 137 return value; | 105 (type == UPB_TYPE_STRING) ? "UTF-8 or ASCII" : "ASCII-8BIT", |
| 106 rb_enc_name(string_encoding)); |
| 107 } |
| 138 } | 108 } |
| 139 | 109 |
| 140 void native_slot_set(upb_fieldtype_t type, VALUE type_class, | 110 void native_slot_set(upb_fieldtype_t type, VALUE type_class, |
| 141 void* memory, VALUE value) { | 111 void* memory, VALUE value) { |
| 142 native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0); | 112 native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0); |
| 143 } | 113 } |
| 144 | 114 |
| 145 void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class, | 115 void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class, |
| 146 void* memory, VALUE value, | 116 void* memory, VALUE value, |
| 147 uint32_t* case_memory, | 117 uint32_t* case_memory, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 173 rb_raise(rb_eTypeError, "Invalid argument for boolean field."); | 143 rb_raise(rb_eTypeError, "Invalid argument for boolean field."); |
| 174 } | 144 } |
| 175 DEREF(memory, int8_t) = val; | 145 DEREF(memory, int8_t) = val; |
| 176 break; | 146 break; |
| 177 } | 147 } |
| 178 case UPB_TYPE_STRING: | 148 case UPB_TYPE_STRING: |
| 179 case UPB_TYPE_BYTES: { | 149 case UPB_TYPE_BYTES: { |
| 180 if (CLASS_OF(value) != rb_cString) { | 150 if (CLASS_OF(value) != rb_cString) { |
| 181 rb_raise(rb_eTypeError, "Invalid argument for string field."); | 151 rb_raise(rb_eTypeError, "Invalid argument for string field."); |
| 182 } | 152 } |
| 183 | 153 native_slot_validate_string_encoding(type, value); |
| 184 DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value); | 154 DEREF(memory, VALUE) = value; |
| 185 break; | 155 break; |
| 186 } | 156 } |
| 187 case UPB_TYPE_MESSAGE: { | 157 case UPB_TYPE_MESSAGE: { |
| 188 if (CLASS_OF(value) == CLASS_OF(Qnil)) { | 158 if (CLASS_OF(value) == CLASS_OF(Qnil)) { |
| 189 value = Qnil; | 159 value = Qnil; |
| 190 } else if (CLASS_OF(value) != type_class) { | 160 } else if (CLASS_OF(value) != type_class) { |
| 191 rb_raise(rb_eTypeError, | 161 rb_raise(rb_eTypeError, |
| 192 "Invalid type %s to assign to submessage field.", | 162 "Invalid type %s to assign to submessage field.", |
| 193 rb_class2name(CLASS_OF(value))); | 163 rb_class2name(CLASS_OF(value))); |
| 194 } | 164 } |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 | 530 |
| 561 | 531 |
| 562 VALUE layout_get(MessageLayout* layout, | 532 VALUE layout_get(MessageLayout* layout, |
| 563 const void* storage, | 533 const void* storage, |
| 564 const upb_fielddef* field) { | 534 const upb_fielddef* field) { |
| 565 void* memory = slot_memory(layout, storage, field); | 535 void* memory = slot_memory(layout, storage, field); |
| 566 uint32_t* oneof_case = slot_oneof_case(layout, storage, field); | 536 uint32_t* oneof_case = slot_oneof_case(layout, storage, field); |
| 567 | 537 |
| 568 if (upb_fielddef_containingoneof(field)) { | 538 if (upb_fielddef_containingoneof(field)) { |
| 569 if (*oneof_case != upb_fielddef_number(field)) { | 539 if (*oneof_case != upb_fielddef_number(field)) { |
| 570 return value_from_default(field); | 540 return Qnil; |
| 571 } | 541 } |
| 572 return native_slot_get(upb_fielddef_type(field), | 542 return native_slot_get(upb_fielddef_type(field), |
| 573 field_type_class(field), | 543 field_type_class(field), |
| 574 memory); | 544 memory); |
| 575 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { | 545 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { |
| 576 return *((VALUE *)memory); | 546 return *((VALUE *)memory); |
| 577 } else { | 547 } else { |
| 578 return native_slot_get(upb_fielddef_type(field), | 548 return native_slot_get(upb_fielddef_type(field), |
| 579 field_type_class(field), | 549 field_type_class(field), |
| 580 memory); | 550 memory); |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 first = false; | 854 first = false; |
| 885 } | 855 } |
| 886 str = rb_str_cat2(str, upb_fielddef_name(field)); | 856 str = rb_str_cat2(str, upb_fielddef_name(field)); |
| 887 str = rb_str_cat2(str, ": "); | 857 str = rb_str_cat2(str, ": "); |
| 888 | 858 |
| 889 str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0)); | 859 str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0)); |
| 890 } | 860 } |
| 891 | 861 |
| 892 return str; | 862 return str; |
| 893 } | 863 } |
| OLD | NEW |