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 |