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 |