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 /** |
| 6 * Per-message type setup. |
| 7 */ |
| 8 class BuilderInfo { |
| 9 Builder _builder; |
| 10 final String messageName; |
| 11 final Map<int, FieldInfo> fieldInfo; |
| 12 final Map<String, FieldInfo> byName; |
| 13 bool hasExtensions = false; |
| 14 bool hasRequiredFields = true; |
| 15 |
| 16 BuilderInfo(Builder this._builder, String this.messageName) |
| 17 : fieldInfo = new Map<int, FieldInfo>(), |
| 18 byName = new Map<String, FieldInfo>(); |
| 19 |
| 20 void add(int tagNumber_, String name, int fieldType_, |
| 21 [MakeDefaultFunc makeDefault_ = null, |
| 22 CreateBuilderFunc subBuilder_ = null, ValueOfFunc valueOf = null]) { |
| 23 FieldInfo i = new FieldInfo(name, tagNumber_, fieldType_, makeDefault_, |
| 24 subBuilder_, valueOf); |
| 25 fieldInfo[tagNumber_] = i; |
| 26 byName[name] = i; |
| 27 } |
| 28 |
| 29 void a(int tagNumber_, String name, int fieldType_, |
| 30 [MakeDefaultFunc makeDefault_ = null, |
| 31 CreateBuilderFunc subBuilder_ = null, |
| 32 ValueOfFunc valueOf = null]) { |
| 33 add(tagNumber_, name, fieldType_, makeDefault_, subBuilder_, valueOf); |
| 34 } |
| 35 |
| 36 // Enum |
| 37 void e(int tagNumber_, String name, int fieldType_, |
| 38 MakeDefaultFunc makeDefault_, ValueOfFunc valueOf) { |
| 39 add(tagNumber_, name, fieldType_, makeDefault_, null, valueOf); |
| 40 } |
| 41 |
| 42 // Repeated message |
| 43 void m(int tagNumber_, String name, CreateBuilderFunc subBuilder_, |
| 44 [var newListFunc = null]) { |
| 45 add(tagNumber_, name, Builder._REPEATED_MESSAGE, |
| 46 newListFunc != null ? newListFunc : () => |
| 47 new PbList<GeneratedMessage>(_builder), subBuilder_, null); |
| 48 } |
| 49 |
| 50 // Repeated non-message |
| 51 void p(int tagNumber_, String name, int fieldType_) { |
| 52 Function createFunc; |
| 53 switch (fieldType_ & ~0x7) { |
| 54 case Builder._BOOL_BIT: |
| 55 createFunc = () => new PbList<bool>(_builder); |
| 56 break; |
| 57 case Builder._BYTES_BIT: |
| 58 createFunc = () => new PbList<List<int>>(_builder); |
| 59 break; |
| 60 case Builder._STRING_BIT: |
| 61 createFunc = () => new PbList<String>(_builder); |
| 62 break; |
| 63 case Builder._FLOAT_BIT: |
| 64 createFunc = () => new PbFloatList(_builder); |
| 65 break; |
| 66 case Builder._DOUBLE_BIT: |
| 67 createFunc = () => new PbList<double>(_builder); |
| 68 break; |
| 69 case Builder._ENUM_BIT: |
| 70 createFunc = () => new PbList<ProtobufEnum>(_builder); |
| 71 break; |
| 72 case Builder._INT32_BIT: |
| 73 case Builder._SINT32_BIT: |
| 74 case Builder._SFIXED32_BIT: |
| 75 createFunc = () => new PbSint32List(_builder); |
| 76 break; |
| 77 case Builder._UINT32_BIT: |
| 78 case Builder._FIXED32_BIT: |
| 79 createFunc = () => new PbUint32List(_builder); |
| 80 break; |
| 81 case Builder._INT64_BIT: |
| 82 case Builder._SINT64_BIT: |
| 83 case Builder._SFIXED64_BIT: |
| 84 // Allow either int or Packed64 entries |
| 85 createFunc = () => new PbSint64List(_builder); |
| 86 break; |
| 87 case Builder._UINT64_BIT: |
| 88 case Builder._FIXED64_BIT: |
| 89 // Allow either int or Packed64 entries |
| 90 createFunc = () => new PbUint64List(_builder); |
| 91 break; |
| 92 case Builder._MESSAGE_BIT: |
| 93 throw new IllegalArgumentException( |
| 94 "use BuilderInfo.m() for repeated messages"); |
| 95 default: |
| 96 throw new IllegalArgumentException("unknown type ${fieldType_}"); |
| 97 } |
| 98 |
| 99 add(tagNumber_, name, fieldType_, createFunc, null, null); |
| 100 } |
| 101 |
| 102 bool containsTagNumber(int tagNumber_) => fieldInfo.containsKey(tagNumber_); |
| 103 |
| 104 Object defaultValue(int tagNumber_) { |
| 105 MakeDefaultFunc func = makeDefault(tagNumber_); |
| 106 return func === null ? null : func(); |
| 107 } |
| 108 |
| 109 // Returns the field name for a given tag number, for debugging purposes. |
| 110 String fieldName(int tagNumber_) { |
| 111 FieldInfo i = fieldInfo[tagNumber_]; |
| 112 return i != null ? i.name : null; |
| 113 } |
| 114 |
| 115 int fieldType(int tagNumber_) { |
| 116 FieldInfo i = fieldInfo[tagNumber_]; |
| 117 return i != null ? i.type : null; |
| 118 } |
| 119 |
| 120 MakeDefaultFunc makeDefault(int tagNumber_) { |
| 121 FieldInfo i = fieldInfo[tagNumber_]; |
| 122 return i != null ? i.makeDefault : null; |
| 123 } |
| 124 |
| 125 bool isInitialized(Map<int, Object> fieldValues) { |
| 126 return fieldInfo.getKeys().every(bool _(int tagNumber_) { |
| 127 return _isFieldInitialized(fieldValues, tagNumber_); |
| 128 }); |
| 129 } |
| 130 |
| 131 CreateBuilderFunc subBuilder(int tagNumber_) { |
| 132 FieldInfo i = fieldInfo[tagNumber_]; |
| 133 return i != null ? i.subBuilder : null; |
| 134 } |
| 135 |
| 136 int tagNumber(String fieldName_) { |
| 137 FieldInfo i = byName[fieldName_]; |
| 138 return i != null ? i.tagNumber : null; |
| 139 } |
| 140 |
| 141 ValueOfFunc valueOfFunc(int tagNumber_) { |
| 142 FieldInfo i = fieldInfo[tagNumber_]; |
| 143 return i != null ? i.valueOf : null; |
| 144 } |
| 145 |
| 146 bool _isFieldInitialized(Map<int, Object> fieldValues, int tagNumber_, |
| 147 [int fieldType_ = null]) { |
| 148 if (fieldType_ == null) { |
| 149 fieldType_ = fieldInfo[tagNumber_].type; |
| 150 } |
| 151 if ((fieldType_ & |
| 152 (Builder._MESSAGE_BIT | Builder._GROUP_BIT)) != 0) { |
| 153 if ((fieldType_ & Builder._REQUIRED_BIT) != 0) { |
| 154 Message message = fieldValues[tagNumber_]; |
| 155 // required message/group must be present and initialized |
| 156 if (message === null || !message.isInitialized()) { |
| 157 return false; |
| 158 } |
| 159 } else if ((fieldType_ & Builder._REPEATED_BIT) != 0) { |
| 160 if (fieldValues.containsKey(tagNumber_)) { |
| 161 // repeated message/group must have all its members initialized |
| 162 List list = fieldValues[tagNumber_]; |
| 163 // For message types that (recursively) contain no required fields, |
| 164 // short-circuit the loop |
| 165 if (!list.isEmpty() && list[0].hasRequiredFields()) { |
| 166 for (Message message in list) { |
| 167 if (!message.isInitialized()) { |
| 168 return false; |
| 169 } |
| 170 } |
| 171 } |
| 172 } |
| 173 } else { |
| 174 Message message = fieldValues[tagNumber_]; |
| 175 // optional message/group must be initialized if it is present |
| 176 if (message !== null && !message.isInitialized()) { |
| 177 return false; |
| 178 } |
| 179 } |
| 180 |
| 181 } else if ((fieldType_ & Builder._REQUIRED_BIT) != 0) { |
| 182 // required 'primitive' must be present |
| 183 if (fieldValues[tagNumber_] === null) { |
| 184 return false; |
| 185 } |
| 186 } |
| 187 return true; |
| 188 } |
| 189 |
| 190 List<String> _findInvalidFields(Map<int, Object> fieldValues, |
| 191 List<String> invalidFields, [String prefix = ""]) { |
| 192 fieldInfo.forEach(_(int tagNumber_, FieldInfo field) { |
| 193 int fieldType_ = field.type; |
| 194 if ((fieldType_ & |
| 195 (Builder._MESSAGE_BIT | Builder._GROUP_BIT)) != 0) { |
| 196 if ((fieldType_ & Builder._REQUIRED_BIT) != 0) { |
| 197 Message message = fieldValues[tagNumber_]; |
| 198 // required message/group must be present |
| 199 if (message === null) { |
| 200 invalidFields.add("${prefix}${field.name}"); |
| 201 } else { |
| 202 message._findInvalidFields(invalidFields, |
| 203 "${prefix}${field.name}."); |
| 204 } |
| 205 } else if ((fieldType_ & Builder._REPEATED_BIT) != 0) { |
| 206 if (fieldValues.containsKey(tagNumber_)) { |
| 207 // repeated message/group must have all its members initialized |
| 208 List list = fieldValues[tagNumber_]; |
| 209 // For messages that (recursively) contain no required fields, |
| 210 // short-circuit the loop |
| 211 if (!list.isEmpty() && list[0].hasRequiredFields()) { |
| 212 int position = 0; |
| 213 for (Message message in list) { |
| 214 if (message.hasRequiredFields()) { |
| 215 message._findInvalidFields(invalidFields, |
| 216 "${prefix}${field.name}[${position}]."); |
| 217 } |
| 218 position++; |
| 219 } |
| 220 } |
| 221 } |
| 222 } else { |
| 223 Message message = fieldValues[tagNumber_]; |
| 224 // required message/group must be present |
| 225 if (message !== null) { |
| 226 message._findInvalidFields(invalidFields, "${prefix}${field.name}.")
; |
| 227 } |
| 228 } |
| 229 |
| 230 } else if((fieldType_ & Builder._REQUIRED_BIT) != 0) { |
| 231 // required 'primitive' must be present |
| 232 if (fieldValues[tagNumber_] === null) { |
| 233 invalidFields.add("${prefix}${field.name}"); |
| 234 } |
| 235 } |
| 236 }); |
| 237 return invalidFields; |
| 238 } |
| 239 } |
OLD | NEW |