| OLD | NEW |
| 1 part of serialization; | 1 part of serialization; |
| 2 | 2 |
| 3 /** | 3 /** |
| 4 * An abstract class for serialization formats. Subclasses define how data | 4 * An abstract class for serialization formats. Subclasses define how data |
| 5 * is read or written to a particular output mechanism. | 5 * is read or written to a particular output mechanism. |
| 6 */ | 6 */ |
| 7 abstract class Format { | 7 abstract class Format { |
| 8 |
| 9 const Format(); |
| 10 |
| 8 /** | 11 /** |
| 9 * Return true if this format stores primitives in their own area and uses | 12 * Return true if this format stores primitives in their own area and uses |
| 10 * references to them (e.g. [SimpleFlatFormat]) and false if primitives | 13 * references to them (e.g. [SimpleFlatFormat]) and false if primitives |
| 11 * are stored directly (e.g. [SimpleJsonFormat], [SimpleMapFormat]). | 14 * are stored directly (e.g. [SimpleJsonFormat], [SimpleMapFormat]). |
| 12 */ | 15 */ |
| 13 bool get shouldUseReferencesForPrimitives => false; | 16 bool get shouldUseReferencesForPrimitives => false; |
| 14 | 17 |
| 15 /** | 18 /** |
| 16 * Generate output for [w] and return it. The particular form of the output | 19 * Generate output for [w] and return it. The particular form of the output |
| 17 * will depend on the format. The format can assume that [w] has data | 20 * will depend on the format. The format can assume that [w] has data |
| (...skipping 15 matching lines...) Expand all Loading... |
| 33 } | 36 } |
| 34 | 37 |
| 35 /** | 38 /** |
| 36 * A format that stores the data in maps which are converted into a JSON | 39 * A format that stores the data in maps which are converted into a JSON |
| 37 * string. Note that the maps aren't nested, and it handles cyclic references | 40 * string. Note that the maps aren't nested, and it handles cyclic references |
| 38 * by converting object references to [Reference] objects. If you want simple | 41 * by converting object references to [Reference] objects. If you want simple |
| 39 * acyclic JSON look at [SimpleJsonFormat]. | 42 * acyclic JSON look at [SimpleJsonFormat]. |
| 40 */ | 43 */ |
| 41 class SimpleMapFormat extends Format { | 44 class SimpleMapFormat extends Format { |
| 42 | 45 |
| 46 const SimpleMapFormat(); |
| 47 |
| 43 /** | 48 /** |
| 44 * Generate output for this format from [w] and return it as a String which | 49 * Generate output for this format from [w] and return it as a String which |
| 45 * is the [json] representation of a nested Map structure. The top level has | 50 * is the [json] representation of a nested Map structure. The top level has |
| 46 * 3 fields, "rules" which may hold a definition of the rules used, | 51 * 3 fields, "rules" which may hold a definition of the rules used, |
| 47 * "data" which holds the serialized data, and "roots", which holds | 52 * "data" which holds the serialized data, and "roots", which holds |
| 48 * [Reference] objects indicating the root objects. Note that roots are | 53 * [Reference] objects indicating the root objects. Note that roots are |
| 49 * necessary because the data is organized in the same way as the object | 54 * necessary because the data is organized in the same way as the object |
| 50 * structure, it's a list of lists holding self-contained maps which only | 55 * structure, it's a list of lists holding self-contained maps which only |
| 51 * refer to other parts via [Reference] objects. | 56 * refer to other parts via [Reference] objects. |
| 52 * This effectively defines a custom JSON serialization format, although | 57 * This effectively defines a custom JSON serialization format, although |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 * Indicate if we should store rule numbers with map/list data so that we | 96 * Indicate if we should store rule numbers with map/list data so that we |
| 92 * will know how to reconstruct it with a read operation. If we don't, this | 97 * will know how to reconstruct it with a read operation. If we don't, this |
| 93 * will be more compliant with things that expect known format JSON as input, | 98 * will be more compliant with things that expect known format JSON as input, |
| 94 * but we won't be able to read back the objects. | 99 * but we won't be able to read back the objects. |
| 95 */ | 100 */ |
| 96 final bool storeRoundTripInfo; | 101 final bool storeRoundTripInfo; |
| 97 | 102 |
| 98 /** | 103 /** |
| 99 * If we store the rule numbers, what key should we use to store them. | 104 * If we store the rule numbers, what key should we use to store them. |
| 100 */ | 105 */ |
| 101 static final String RULE = "_rule"; | 106 static const String RULE = "_rule"; |
| 102 static final String RULES = "_rules"; | 107 static const String RULES = "_rules"; |
| 103 static final String DATA = "_data"; | 108 static const String DATA = "_data"; |
| 104 static final String ROOTS = "_root"; | 109 static const String ROOTS = "_root"; |
| 105 | 110 |
| 106 SimpleJsonFormat({this.storeRoundTripInfo : false}); | 111 const SimpleJsonFormat({this.storeRoundTripInfo : false}); |
| 107 | 112 |
| 108 /** | 113 /** |
| 109 * Generate output for this format from [w] and return it as | 114 * Generate output for this format from [w] and return it as |
| 110 * the [json] representation of a nested Map structure. | 115 * the [json] representation of a nested Map structure. |
| 111 */ | 116 */ |
| 112 generateOutput(Writer w) { | 117 generateOutput(Writer w) { |
| 113 jsonify(w); | 118 jsonify(w); |
| 114 var root = w._rootReferences().first; | 119 var root = w._rootReferences().first; |
| 115 if (root is Reference) root = w.stateForReference(root); | 120 if (root is Reference) root = w.stateForReference(root); |
| 116 if (w.selfDescribing && storeRoundTripInfo) { | 121 if (w.selfDescribing && storeRoundTripInfo) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 * more space-efficient than the map formats, but much less human-readable. | 235 * more space-efficient than the map formats, but much less human-readable. |
| 231 * Simple usage is to turn this into JSON for transmission. | 236 * Simple usage is to turn this into JSON for transmission. |
| 232 */ | 237 */ |
| 233 class SimpleFlatFormat extends Format { | 238 class SimpleFlatFormat extends Format { |
| 234 bool get shouldUseReferencesForPrimitives => true; | 239 bool get shouldUseReferencesForPrimitives => true; |
| 235 | 240 |
| 236 /** | 241 /** |
| 237 * For each rule we store data to indicate whether it will be reconstructed | 242 * For each rule we store data to indicate whether it will be reconstructed |
| 238 * as a primitive, a list or a map. | 243 * as a primitive, a list or a map. |
| 239 */ | 244 */ |
| 240 static final int STORED_AS_LIST = 1; | 245 static const int STORED_AS_LIST = 1; |
| 241 static final int STORED_AS_MAP = 2; | 246 static const int STORED_AS_MAP = 2; |
| 242 static final int STORED_AS_PRIMITIVE = 3; | 247 static const int STORED_AS_PRIMITIVE = 3; |
| 248 |
| 249 const SimpleFlatFormat(); |
| 243 | 250 |
| 244 /** | 251 /** |
| 245 * Generate output for this format from [w]. This will return a List with | 252 * Generate output for this format from [w]. This will return a List with |
| 246 * three entries, corresponding to the "rules", "data", and "roots" from | 253 * three entries, corresponding to the "rules", "data", and "roots" from |
| 247 * [SimpleMapFormat]. The data is stored as a single List containing | 254 * [SimpleMapFormat]. The data is stored as a single List containing |
| 248 * primitives. | 255 * primitives. |
| 249 */ | 256 */ |
| 250 List generateOutput(Writer w) { | 257 List generateOutput(Writer w) { |
| 251 var result = new List(3); | 258 var result = new List(3); |
| 252 var flatData = []; | 259 var flatData = []; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 283 } | 290 } |
| 284 } | 291 } |
| 285 | 292 |
| 286 /** | 293 /** |
| 287 * Write [entries], which contains Lists. Either the lists are variable | 294 * Write [entries], which contains Lists. Either the lists are variable |
| 288 * length, in which case we add a length field, or they are fixed length, in | 295 * length, in which case we add a length field, or they are fixed length, in |
| 289 * which case we don't, and assume the [rule] will know how to read the | 296 * which case we don't, and assume the [rule] will know how to read the |
| 290 * right length when we read it back. We expect everything in the list to be | 297 * right length when we read it back. We expect everything in the list to be |
| 291 * a reference, which is stored as two numbers. | 298 * a reference, which is stored as two numbers. |
| 292 */ | 299 */ |
| 293 writeLists(SerializationRule rule, List<List> entries, List target) { | 300 void writeLists(SerializationRule rule, List<List> entries, List target) { |
| 294 target.add(STORED_AS_LIST); | 301 target.add(STORED_AS_LIST); |
| 295 for (var eachEntry in entries) { | 302 for (var eachEntry in entries) { |
| 296 if (rule.hasVariableLengthEntries) { | 303 if (rule.hasVariableLengthEntries) { |
| 297 target.add(eachEntry.length); | 304 target.add(eachEntry.length); |
| 298 } | 305 } |
| 299 for (var eachReference in eachEntry) { | 306 for (var eachReference in eachEntry) { |
| 300 writeReference(eachReference, target); | 307 writeReference(eachReference, target); |
| 301 } | 308 } |
| 302 } | 309 } |
| 303 } | 310 } |
| 304 | 311 |
| 305 /** | 312 /** |
| 306 * Write [entries], which contains Maps. Either the Maps are variable | 313 * Write [entries], which contains Maps. Either the Maps are variable |
| 307 * length, in which case we add a length field, or they are fixed length, in | 314 * length, in which case we add a length field, or they are fixed length, in |
| 308 * which case we don't, and assume the [rule] will know how to read the | 315 * which case we don't, and assume the [rule] will know how to read the |
| 309 * right length when we read it back. Then we write alternating keys and | 316 * right length when we read it back. Then we write alternating keys and |
| 310 * values. We expect the values to be references, which we store as | 317 * values. We expect the values to be references, which we store as |
| 311 * two numbers. | 318 * two numbers. |
| 312 */ | 319 */ |
| 313 writeMaps(SerializationRule rule, List<Map> entries, List target) { | 320 void writeMaps(SerializationRule rule, List<Map> entries, List target) { |
| 314 target.add(STORED_AS_MAP); | 321 target.add(STORED_AS_MAP); |
| 315 for (var eachEntry in entries) { | 322 for (var eachEntry in entries) { |
| 316 if (rule.hasVariableLengthEntries) { | 323 if (rule.hasVariableLengthEntries) { |
| 317 target.add(eachEntry.length); | 324 target.add(eachEntry.length); |
| 318 } | 325 } |
| 319 eachEntry.forEach((key, value) { | 326 eachEntry.forEach((key, value) { |
| 320 writeReference(key, target); | 327 writeReference(key, target); |
| 321 writeReference(value, target); | 328 writeReference(value, target); |
| 322 }); | 329 }); |
| 323 } | 330 } |
| 324 } | 331 } |
| 325 | 332 |
| 326 /** | 333 /** |
| 327 * Write [entries], which contains simple objects which we can put directly | 334 * Write [entries], which contains simple objects which we can put directly |
| 328 * into [target]. | 335 * into [target]. |
| 329 */ | 336 */ |
| 330 writeObjects(List entries, List target) { | 337 void writeObjects(List entries, List target) { |
| 331 target.add(STORED_AS_PRIMITIVE); | 338 target.add(STORED_AS_PRIMITIVE); |
| 332 for (var each in entries) { | 339 for (var each in entries) { |
| 333 if (!isPrimitive(each)) throw new SerializationException("Invalid data"); | 340 if (!isPrimitive(each)) throw new SerializationException("Invalid data"); |
| 334 } | 341 } |
| 335 target.addAll(entries); | 342 target.addAll(entries); |
| 336 } | 343 } |
| 337 | 344 |
| 338 /** | 345 /** |
| 339 * Write [eachRef] to [target]. It will be written as two ints. If [eachRef] | 346 * Write [eachRef] to [target]. It will be written as two ints. If [eachRef] |
| 340 * is null it will be written as two nulls. | 347 * is null it will be written as two nulls. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 */ | 453 */ |
| 447 readPrimitives(Iterator input, SerializationRule rule, int length) { | 454 readPrimitives(Iterator input, SerializationRule rule, int length) { |
| 448 var ruleData = []; | 455 var ruleData = []; |
| 449 for (var i = 0; i < length; i++) { | 456 for (var i = 0; i < length; i++) { |
| 450 ruleData.add(_next(input)); | 457 ruleData.add(_next(input)); |
| 451 } | 458 } |
| 452 return ruleData; | 459 return ruleData; |
| 453 } | 460 } |
| 454 | 461 |
| 455 /** Read the next Reference from the input. */ | 462 /** Read the next Reference from the input. */ |
| 456 nextReferenceFrom(Iterator input, Reader r) { | 463 Reference nextReferenceFrom(Iterator input, Reader r) { |
| 457 var a = _next(input); | 464 var a = _next(input); |
| 458 var b = _next(input); | 465 var b = _next(input); |
| 459 if (a == null) { | 466 if (a == null) { |
| 460 return null; | 467 return null; |
| 461 } else { | 468 } else { |
| 462 return new Reference(r, a, b); | 469 return new Reference(r, a, b); |
| 463 } | 470 } |
| 464 } | 471 } |
| 465 | 472 |
| 466 /** Return the next element from the input. */ | 473 /** Return the next element from the input. */ |
| 467 _next(Iterator input) { | 474 _next(Iterator input) { |
| 468 input.moveNext(); | 475 input.moveNext(); |
| 469 return input.current; | 476 return input.current; |
| 470 } | 477 } |
| 471 } | 478 } |
| OLD | NEW |