OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 class ProtobufField { |
| 6 |
| 7 // Whitespace |
| 8 static final String sp = MessageGenerator.sp; |
| 9 |
| 10 static final RegExp HEX_LITERAL_REGEX = |
| 11 const RegExp(@"^0x[0-9a-f]+$", false, true); |
| 12 static final RegExp INTEGER_LITERAL_REGEX = const RegExp(@"^[+-]?[0-9]+$"); |
| 13 static final RegExp DECIMAL_LITERAL_REGEX_A = |
| 14 const RegExp(@"^[+-]?([0-9]*)\.[0-9]+(e[+-]?[0-9]+)?$", false, true); |
| 15 static final RegExp DECIMAL_LITERAL_REGEX_B = |
| 16 const RegExp(@"^[+-]?[0-9]+e[+-]?[0-9]+$", false, true); |
| 17 |
| 18 static int _maxIndex = 0; |
| 19 |
| 20 static void _resetIndices() { |
| 21 _maxIndex = 0; |
| 22 } |
| 23 |
| 24 static int _getIndex() { |
| 25 _maxIndex++; |
| 26 return _maxIndex; |
| 27 } |
| 28 |
| 29 GoogleProtobuf_FieldDescriptorProto _field; |
| 30 GenerationContext _context; |
| 31 |
| 32 int _index; |
| 33 int get index() => _index; |
| 34 |
| 35 String _baseType; |
| 36 String get baseType() => _baseType; |
| 37 |
| 38 String _typeString; |
| 39 String get typeString() => _typeString; |
| 40 |
| 41 String _codedStreamType; |
| 42 String get codedStreamType() => _codedStreamType; |
| 43 |
| 44 bool _repeats = false; |
| 45 bool get repeats() => _repeats; |
| 46 bool get single() => !repeats; |
| 47 |
| 48 bool get group() => type === GoogleProtobuf_FieldDescriptorProto_Type.TYPE_GRO
UP; |
| 49 bool get message() => type === GoogleProtobuf_FieldDescriptorProto_Type.TYPE_M
ESSAGE; |
| 50 bool get enum() => type === GoogleProtobuf_FieldDescriptorProto_Type.TYPE_ENUM
; |
| 51 bool get primitive() => !group && !message; |
| 52 |
| 53 // Initializer to be applied in the initialize() function |
| 54 String _initialization = null; |
| 55 String get initialization() => _initialization; |
| 56 bool get hasInitialization() => _initialization !== null; |
| 57 |
| 58 bool _required = false; |
| 59 bool get required() => _required; |
| 60 bool get optional() => !required; // includes repeated |
| 61 |
| 62 // True if the field is to be encoded with [packed=true] encoding |
| 63 bool _packed = false; |
| 64 bool get packed() => _packed; |
| 65 |
| 66 // True if the fields's type can handle [packed=true] encoding |
| 67 bool _packable = false; |
| 68 bool get packable() => _packable; |
| 69 |
| 70 // delegate methods |
| 71 String get name() => _field.name; |
| 72 int get number() => _field.number; |
| 73 GoogleProtobuf_FieldDescriptorProto_Label get label() => _field.label; |
| 74 GoogleProtobuf_FieldDescriptorProto_Type get type() => _field.type; |
| 75 GoogleProtobuf_FieldOptions get options() => _field.options; |
| 76 String get typeName() => _field.typeName; |
| 77 |
| 78 String _shortName(String name) { |
| 79 switch (name) { |
| 80 case "OPTIONAL_BOOL": return "OB"; |
| 81 case "OPTIONAL_BYTES": return "OY"; |
| 82 case "OPTIONAL_STRING": return "OS"; |
| 83 case "OPTIONAL_FLOAT": return "OF"; |
| 84 case "OPTIONAL_DOUBLE": return "OD"; |
| 85 case "OPTIONAL_ENUM": return "OE"; |
| 86 case "OPTIONAL_GROUP": return "OG"; |
| 87 case "OPTIONAL_INT32": return "O3"; |
| 88 case "OPTIONAL_INT64": return "O6"; |
| 89 case "OPTIONAL_UINT32": return "OU3"; |
| 90 case "OPTIONAL_UINT64": return "OU6"; |
| 91 case "OPTIONAL_SINT32": return "OS3"; |
| 92 case "OPTIONAL_SINT64": return "OS6"; |
| 93 case "OPTIONAL_FIXED32": return "OF3"; |
| 94 case "OPTIONAL_FIXED64": return "OF6"; |
| 95 case "OPTIONAL_SFIXED32": return "OSF3"; |
| 96 case "OPTIONAL_SFIXED64": return "OSF6"; |
| 97 case "OPTIONAL_MESSAGE": return "OM"; |
| 98 |
| 99 case "REQUIRED_BOOL": return "QB"; |
| 100 case "REQUIRED_BYTES": return "QY"; |
| 101 case "REQUIRED_STRING": return "QS"; |
| 102 case "REQUIRED_FLOAT": return "QF"; |
| 103 case "REQUIRED_DOUBLE": return "QD"; |
| 104 case "REQUIRED_ENUM": return "QE"; |
| 105 case "REQUIRED_GROUP": return "QG"; |
| 106 case "REQUIRED_INT32": return "Q3"; |
| 107 case "REQUIRED_INT64": return "Q6"; |
| 108 case "REQUIRED_UINT32": return "QU3"; |
| 109 case "REQUIRED_UINT64": return "QU6"; |
| 110 case "REQUIRED_SINT32": return "QS3"; |
| 111 case "REQUIRED_SINT64": return "QS6"; |
| 112 case "REQUIRED_FIXED32": return "QF3"; |
| 113 case "REQUIRED_FIXED64": return "QF6"; |
| 114 case "REQUIRED_SFIXED32": return "QSF3"; |
| 115 case "REQUIRED_SFIXED64": return "QSF6"; |
| 116 case "REQUIRED_MESSAGE": return "QM"; |
| 117 |
| 118 case "REPEATED_BOOL": return "PB"; |
| 119 case "REPEATED_BYTES": return "PY"; |
| 120 case "REPEATED_STRING": return "PS"; |
| 121 case "REPEATED_FLOAT": return "PF"; |
| 122 case "REPEATED_DOUBLE": return "PD"; |
| 123 case "REPEATED_ENUM": return "PE"; |
| 124 case "REPEATED_GROUP": return "PG"; |
| 125 case "REPEATED_INT32": return "P3"; |
| 126 case "REPEATED_INT64": return "P6"; |
| 127 case "REPEATED_UINT32": return "PU3"; |
| 128 case "REPEATED_UINT64": return "PU6"; |
| 129 case "REPEATED_SINT32": return "PS3"; |
| 130 case "REPEATED_SINT64": return "PS6"; |
| 131 case "REPEATED_FIXED32": return "PF3"; |
| 132 case "REPEATED_FIXED64": return "PF6"; |
| 133 case "REPEATED_SFIXED32": return "PSF3"; |
| 134 case "REPEATED_SFIXED64": return "PSF6"; |
| 135 case "REPEATED_MESSAGE": return "PM"; |
| 136 |
| 137 case "PACKED_INT32": return "K3"; |
| 138 case "PACKED_INT64": return "K6"; |
| 139 |
| 140 case "PACKED_BOOL": return "KB"; |
| 141 case "PACKED_ENUM": return "KE"; |
| 142 case "PACKED_FLOAT": return "KF"; |
| 143 case "PACKED_DOUBLE": return "KD"; |
| 144 case "PACKED_INT32": return "K3"; |
| 145 case "PACKED_INT64": return "K6"; |
| 146 case "PACKED_SINT32": return "KS3"; |
| 147 case "PACKED_SINT64": return "KS6"; |
| 148 case "PACKED_UINT32": return "KU3"; |
| 149 case "PACKED_UINT64": return "KU6"; |
| 150 case "PACKED_FIXED32": return "KF3"; |
| 151 case "PACKED_FIXED64": return "KF6"; |
| 152 case "PACKED_SFIXED32": return "KSF3"; |
| 153 case "PACKED_SFIXED64": return "KSF6"; |
| 154 } |
| 155 return name; |
| 156 } |
| 157 |
| 158 String get shortTypeName() { |
| 159 String type; |
| 160 if (required) { |
| 161 type = "REQUIRED_"; |
| 162 } else if (packed) { |
| 163 type = "PACKED_"; |
| 164 } else if (repeats) { |
| 165 type = "REPEATED_"; |
| 166 } else if (optional) { |
| 167 type = "OPTIONAL_"; |
| 168 } else { |
| 169 throw "$this"; |
| 170 } |
| 171 type = "${type}${codedStreamType.toUpperCase()}"; |
| 172 return _shortName(type); |
| 173 } |
| 174 |
| 175 ProtobufField(GoogleProtobuf_FieldDescriptorProto this._field, this._context)
{ |
| 176 String _singleFieldType(String typeString) => typeString; |
| 177 String _repeatingFieldType(String typeString) => "List<$typeString>"; |
| 178 |
| 179 _required = |
| 180 _field.label === GoogleProtobuf_FieldDescriptorProto_Label.LABEL_REQUIRE
D; |
| 181 _repeats = |
| 182 _field.label === GoogleProtobuf_FieldDescriptorProto_Label.LABEL_REPEATE
D; |
| 183 |
| 184 var write; |
| 185 if (repeats) { |
| 186 _packed = _field.options == null ? false : _field.options.packed; |
| 187 _index = -1; |
| 188 write = _repeatingFieldType; |
| 189 } else { |
| 190 _index = _getIndex(); |
| 191 write = _singleFieldType; |
| 192 } |
| 193 |
| 194 switch (_field.type) { |
| 195 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_BOOL: |
| 196 _baseType = "bool"; |
| 197 _typeString = write("bool"); |
| 198 _packable = true; |
| 199 _codedStreamType = "Bool"; |
| 200 if (!repeats) { |
| 201 if (_field.hasDefaultValue() && "false" != _field.defaultValue) { |
| 202 _initialization = "()${sp}=>${sp}${_field.defaultValue}"; |
| 203 } |
| 204 } |
| 205 break; |
| 206 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FLOAT: |
| 207 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_DOUBLE: |
| 208 _baseType = "double"; |
| 209 _typeString = write("double"); |
| 210 _packable = true; |
| 211 _codedStreamType = |
| 212 (_field.type == GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FLOAT)
? |
| 213 "Float" : "Double"; |
| 214 if (!repeats) { |
| 215 if (_field.hasDefaultValue() && |
| 216 ("0.0" != _field.defaultValue || "0" != _field.defaultValue)) { |
| 217 switch(true) { |
| 218 case _field.defaultValue == "inf": |
| 219 _initialization = "()${sp}=>${sp}double.INFINITY"; |
| 220 break; |
| 221 case _field.defaultValue == "-inf": |
| 222 _initialization = "()${sp}=>${sp}double.NEGATIVE_INFINITY"; |
| 223 break; |
| 224 case _field.defaultValue == "nan": |
| 225 _initialization = "()${sp}=>${sp}double.NAN"; |
| 226 break; |
| 227 case HEX_LITERAL_REGEX.hasMatch(_field.defaultValue): |
| 228 _initialization = "()${sp}=>${sp}(${_field.defaultValue})" |
| 229 ".toDouble()"; |
| 230 break; |
| 231 case INTEGER_LITERAL_REGEX.hasMatch(_field.defaultValue): |
| 232 _initialization = "()${sp}=>${sp}${_field.defaultValue}.0"; |
| 233 break; |
| 234 case DECIMAL_LITERAL_REGEX_A.hasMatch(_field.defaultValue): |
| 235 case DECIMAL_LITERAL_REGEX_B.hasMatch(_field.defaultValue): |
| 236 _initialization = "()${sp}=>${sp}${_field.defaultValue}"; |
| 237 break; |
| 238 default: |
| 239 throw InvalidDefaultValue.invalidDoubleValue(_field.name, |
| 240 _field.defaultValue); |
| 241 } |
| 242 } |
| 243 } |
| 244 break; |
| 245 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_INT32: |
| 246 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_INT64: |
| 247 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_UINT32: |
| 248 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_UINT64: |
| 249 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SINT32: |
| 250 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SINT64: |
| 251 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FIXED32: |
| 252 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FIXED64: |
| 253 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SFIXED32: |
| 254 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SFIXED64: |
| 255 _baseType = "int"; |
| 256 _typeString = write("int"); |
| 257 _packable = true; |
| 258 switch (_field.type) { |
| 259 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_INT32: |
| 260 _codedStreamType = "Int32"; |
| 261 break; |
| 262 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_INT64: |
| 263 _codedStreamType = "Int64"; |
| 264 break; |
| 265 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_UINT32: |
| 266 _codedStreamType = "Uint32"; |
| 267 break; |
| 268 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_UINT64: |
| 269 _codedStreamType = "Uint64"; |
| 270 break; |
| 271 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SINT32: |
| 272 _codedStreamType = "Sint32"; |
| 273 break; |
| 274 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SINT64: |
| 275 _codedStreamType = "Sint64"; |
| 276 break; |
| 277 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FIXED32: |
| 278 _codedStreamType = "Fixed32"; |
| 279 break; |
| 280 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FIXED64: |
| 281 _codedStreamType = "Fixed64"; |
| 282 break; |
| 283 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SFIXED32: |
| 284 _codedStreamType = "Sfixed32"; |
| 285 break; |
| 286 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SFIXED64: |
| 287 _codedStreamType = "Sfixed64"; |
| 288 break; |
| 289 } |
| 290 if (!repeats) { |
| 291 if (_field.hasDefaultValue() && "0" != _field.defaultValue) { |
| 292 _initialization = "()${sp}=>${sp}${_field.defaultValue}"; |
| 293 } |
| 294 } |
| 295 break; |
| 296 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_STRING: |
| 297 _baseType = "String"; |
| 298 _typeString = write("String"); |
| 299 _codedStreamType = "String"; |
| 300 if (!repeats) { |
| 301 if (_field.hasDefaultValue() && !_field.defaultValue.isEmpty()) { |
| 302 _initialization = "()${sp}=>${sp}'${_field.defaultValue}'"; |
| 303 } |
| 304 } |
| 305 break; |
| 306 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_BYTES: |
| 307 _baseType = "List<int>"; |
| 308 _typeString = write("List<int>"); |
| 309 _codedStreamType = "Bytes"; |
| 310 if (!repeats) { |
| 311 if (_field.hasDefaultValue() && !_field.defaultValue.isEmpty()) { |
| 312 List<int> bytes = _field.defaultValue.charCodes(); |
| 313 bool firstTime = true; |
| 314 |
| 315 StringBuffer sb = new StringBuffer(); |
| 316 sb.add("<int>["); |
| 317 for (int b in bytes) { |
| 318 if (!firstTime) { |
| 319 sb.add(","); |
| 320 } |
| 321 firstTime = false; |
| 322 sb.add("0x${b.toRadixString(16)}"); |
| 323 } |
| 324 sb.add("]"); |
| 325 _initialization = "()${sp}=>${sp}$sb"; |
| 326 } |
| 327 } |
| 328 break; |
| 329 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_GROUP: |
| 330 ProtobufContainer groupType = _context[typeName]; |
| 331 if (groupType !== null) { |
| 332 _baseType = groupType.classname; |
| 333 _typeString = write(groupType.classname); |
| 334 _codedStreamType = "Group"; |
| 335 } else { |
| 336 throw "FAILURE: Unknown group type reference ${_field.typeName}"; |
| 337 } |
| 338 _initialization = "()${sp}=>${sp}${baseType}.defaultInstance"; |
| 339 break; |
| 340 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_MESSAGE: |
| 341 ProtobufContainer messageType = _context[typeName]; |
| 342 if (messageType !== null) { |
| 343 _baseType = messageType.classname; |
| 344 _typeString = write(messageType.classname); |
| 345 _codedStreamType = "Message"; |
| 346 } else { |
| 347 throw "FAILURE: Unknown message type reference ${_field.typeName}"; |
| 348 } |
| 349 _initialization = "()${sp}=>${sp}${baseType}.defaultInstance"; |
| 350 break; |
| 351 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_ENUM: |
| 352 EnumGenerator enumType = _context[typeName]; |
| 353 if (enumType !== null) { |
| 354 _baseType = enumType.classname; |
| 355 _typeString = write(enumType.classname); |
| 356 _codedStreamType = "Enum"; |
| 357 _packable = true; |
| 358 if (!repeats) { |
| 359 if (_field.hasDefaultValue() && !_field.defaultValue.isEmpty()) { |
| 360 _initialization = |
| 361 "()${sp}=>${sp}${enumType.classname}.${_field.defaultValue}"; |
| 362 } else if (enumType._canonicalValues.length > 0) { |
| 363 _initialization = |
| 364 "()${sp}=>${sp}${enumType.classname}." |
| 365 "${enumType._canonicalValues[0].name}"; |
| 366 } |
| 367 } |
| 368 } else { |
| 369 throw "FAILURE: Unknown enum type reference ${_field.typeName}"; |
| 370 } |
| 371 break; |
| 372 default: |
| 373 throw "Unknown type ${_field.type.name}"; |
| 374 // no default -- should be an error |
| 375 } |
| 376 |
| 377 if (repeats) { |
| 378 _initialization = "()${sp}=>${sp}new PbList(this)"; |
| 379 } |
| 380 } |
| 381 |
| 382 // camelCase field name |
| 383 String get externalFieldName() { |
| 384 // For groups, use capitalization of 'typeName' rather than 'name' |
| 385 if (codedStreamType == "Group") { |
| 386 String name = _field.typeName; |
| 387 int index = name.lastIndexOf("."); |
| 388 if (index != -1) { |
| 389 name = name.substring(index + 1); |
| 390 } |
| 391 |
| 392 List<String> parts = name.split("_"); |
| 393 parts = parts.map((String x) => "${x[0].toUpperCase()}${x.substring(1)}"); |
| 394 name = Strings.join(parts, ''); |
| 395 if (name.length > 0) { |
| 396 name = "${name[0].toLowerCase()}${name.substring(1)}"; |
| 397 } |
| 398 return name; |
| 399 } |
| 400 return underscoresToCamelCase(_field.name); |
| 401 } |
| 402 |
| 403 // underscore-prefixed camelCase field name |
| 404 String get internalFieldName() => "_${externalFieldName}"; |
| 405 |
| 406 // TitleCase field name |
| 407 String get titlecaseFieldName() { |
| 408 // For groups, use capitalization of 'typeName' rather than 'name' |
| 409 if (codedStreamType == "Group") { |
| 410 String name = externalFieldName; |
| 411 if (name.length > 0) { |
| 412 name = "${name[0].toUpperCase()}${name.substring(1)}"; |
| 413 } |
| 414 return name; |
| 415 } |
| 416 return underscoresToCamelCase(_field.name, true); |
| 417 } |
| 418 |
| 419 int get wireType() { |
| 420 switch (_field.type) { |
| 421 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_INT32: |
| 422 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_INT64: |
| 423 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_UINT32: |
| 424 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_UINT64: |
| 425 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SINT32: |
| 426 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SINT64: |
| 427 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_BOOL: |
| 428 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_ENUM: |
| 429 return 0; // Varint |
| 430 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_DOUBLE: |
| 431 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FIXED64: |
| 432 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SFIXED64: |
| 433 return 1; // 64-bit |
| 434 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_STRING: |
| 435 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_BYTES: |
| 436 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_MESSAGE: |
| 437 return 2; // Length-delimited |
| 438 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_GROUP: |
| 439 return 3; // Start group |
| 440 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FLOAT: |
| 441 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_FIXED32: |
| 442 case GoogleProtobuf_FieldDescriptorProto_Type.TYPE_SFIXED32: |
| 443 return 5; // 32-bit |
| 444 } |
| 445 } |
| 446 } |
OLD | NEW |