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