Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: pkg/serialization/lib/src/reader_writer.dart

Issue 14793016: pkg/serialization types cleanup (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: const is better, right? Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of serialization; 5 part of serialization;
6 6
7 /** 7 /**
8 * This writes out the state of the objects to an external format. It holds 8 * This writes out the state of the objects to an external format. It holds
9 * all of the intermediate state needed. The primary API for it is the 9 * all of the intermediate state needed. The primary API for it is the
10 * [write] method. 10 * [write] method.
(...skipping 13 matching lines...) Expand all
24 * the full set of objects to be written.*/ 24 * the full set of objects to be written.*/
25 Trace trace; 25 Trace trace;
26 26
27 /** 27 /**
28 * When we write out objects, should we also write out a description 28 * When we write out objects, should we also write out a description
29 * of the rules for the serialization. This defaults to the corresponding 29 * of the rules for the serialization. This defaults to the corresponding
30 * value on the Serialization. 30 * value on the Serialization.
31 */ 31 */
32 bool selfDescribing; 32 bool selfDescribing;
33 33
34 Format format = new SimpleMapFormat(); 34 final Format format;
35 35
36 /** 36 /**
37 * Objects that cannot be represented in-place in the serialized form need 37 * Objects that cannot be represented in-place in the serialized form need
38 * to have references to them stored. The [Reference] objects are computed 38 * to have references to them stored. The [Reference] objects are computed
39 * once and stored here for each object. This provides some space-saving, 39 * once and stored here for each object. This provides some space-saving,
40 * but also serves to record which objects we have already seen. 40 * but also serves to record which objects we have already seen.
41 */ 41 */
42 final Map<dynamic, Reference> references = 42 final Map<dynamic, Reference> references =
43 new IdentityMap<Object, Reference>(); 43 new IdentityMap<Object, Reference>();
44 44
45 /** 45 /**
46 * The state of objects that need to be serialized is stored here. 46 * The state of objects that need to be serialized is stored here.
47 * Each rule has a number, and rules keep track of the objects that they 47 * Each rule has a number, and rules keep track of the objects that they
48 * serialize, in order. So the state of any object can be found by indexing 48 * serialize, in order. So the state of any object can be found by indexing
49 * from the rule number and the object number within the rule. 49 * from the rule number and the object number within the rule.
50 * The actual representation of the state is determined by the rule. Lists 50 * The actual representation of the state is determined by the rule. Lists
51 * and Maps are common, but it is arbitrary. 51 * and Maps are common, but it is arbitrary.
52 */ 52 */
53 final List<List> states = new List<List>(); 53 final List<List> states = new List<List>();
54 54
55 /** Return the list of rules we use. */ 55 /** Return the list of rules we use. */
56 List<SerializationRule> get rules => serialization._rules; 56 List<SerializationRule> get rules => serialization.rules;
57 57
58 /** 58 /**
59 * Creates a new [Writer] that uses the rules from its parent 59 * Creates a new [Writer] that uses the rules from its parent
60 * [Serialization]. Serializations do not keep any state 60 * [Serialization]. Serializations do not keep any state
61 * related to a particular read/write, so the same one can be used 61 * related to a particular read/write, so the same one can be used
62 * for multiple different Readers/Writers. 62 * for multiple different Readers/Writers.
63 */ 63 */
64 Writer(this.serialization, [Format newFormat]) { 64 Writer(this.serialization, [Format newFormat]) :
65 format = (newFormat == null) ? const SimpleMapFormat() : newFormat {
65 trace = new Trace(this); 66 trace = new Trace(this);
66 selfDescribing = serialization.selfDescribing; 67 selfDescribing = serialization.selfDescribing;
67 if (newFormat != null) format = newFormat;
68 } 68 }
69 69
70 /** 70 /**
71 * This is the main API for a [Writer]. It writes the objects and returns 71 * This is the main API for a [Writer]. It writes the objects and returns
72 * the serialized representation, as determined by [format]. 72 * the serialized representation, as determined by [format].
73 */ 73 */
74 write(anObject) { 74 write(anObject) {
75 trace.addRoot(anObject); 75 trace.addRoot(anObject);
76 trace.traceAll(); 76 trace.traceAll();
77 _flatten(); 77 _flatten();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 138
139 /** 139 /**
140 * Returns a serialized version of the [SerializationRule]s used to write 140 * Returns a serialized version of the [SerializationRule]s used to write
141 * the data, if [selfDescribing] is true, otherwise returns null. 141 * the data, if [selfDescribing] is true, otherwise returns null.
142 */ 142 */
143 serializedRules() { 143 serializedRules() {
144 if (!selfDescribing) return null; 144 if (!selfDescribing) return null;
145 var meta = serialization.ruleSerialization(); 145 var meta = serialization.ruleSerialization();
146 var writer = new Writer(meta, format); 146 var writer = new Writer(meta, format);
147 writer.selfDescribing = false; 147 writer.selfDescribing = false;
148 return writer.write(serialization._rules); 148 return writer.write(serialization.rules);
149 } 149 }
150 150
151 /** Record a [state] entry for a particular rule. */ 151 /** Record a [state] entry for a particular rule. */
152 void _addStateForRule(eachRule, state) { 152 void _addStateForRule(eachRule, state) {
153 _growStates(eachRule); 153 _growStates(eachRule);
154 states[eachRule.number].add(state); 154 states[eachRule.number].add(state);
155 } 155 }
156 156
157 /** Find what the object number for the thing we're about to add will be.*/ 157 /** Find what the object number for the thing we're about to add will be.*/
158 int _nextObjectNumberFor(SerializationRule rule) { 158 int _nextObjectNumberFor(SerializationRule rule) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 */ 190 */
191 int _objectNumberFor(object) { 191 int _objectNumberFor(object) {
192 var reference = references[object]; 192 var reference = references[object];
193 return (reference == null) ? -1 : reference.objectNumber; 193 return (reference == null) ? -1 : reference.objectNumber;
194 } 194 }
195 195
196 /** 196 /**
197 * Return a list of [Reference] objects pointing to our roots. This will be 197 * Return a list of [Reference] objects pointing to our roots. This will be
198 * stored in the output under "roots" in the default format. 198 * stored in the output under "roots" in the default format.
199 */ 199 */
200 _rootReferences() => trace.roots.map(_referenceFor).toList(); 200 List _rootReferences() => trace.roots.map(_referenceFor).toList();
201 201
202 /** 202 /**
203 * Given an object, return a reference for it if one exists. If there's 203 * Given an object, return a reference for it if one exists. If there's
204 * no reference, return the object itself. Once we have finished the tracing 204 * no reference, return the object itself. Once we have finished the tracing
205 * step, all objects that should have a reference (roughly speaking, 205 * step, all objects that should have a reference (roughly speaking,
206 * non-primitives) can be relied on to have a reference. 206 * non-primitives) can be relied on to have a reference.
207 */ 207 */
208 _referenceFor(object) { 208 _referenceFor(object) {
209 var result = references[object]; 209 var result = references[object];
210 return (result == null) ? object : result; 210 return (result == null) ? object : result;
211 } 211 }
212 212
213 /** 213 /**
214 * Return true if the [Serialization.namedObjects] collection has a 214 * Return true if the [Serialization.namedObjects] collection has a
215 * reference to [object]. 215 * reference to [object].
216 */ 216 */
217 // TODO(alanknight): Should the writer also have its own namedObjects 217 // TODO(alanknight): Should the writer also have its own namedObjects
218 // collection specific to the particular write, or is that just adding 218 // collection specific to the particular write, or is that just adding
219 // complexity for little value? 219 // complexity for little value?
220 hasNameFor(object) => serialization._hasNameFor(object); 220 bool hasNameFor(object) => serialization._hasNameFor(object);
221 221
222 /** 222 /**
223 * Return the name we have for this object in the [Serialization.namedObjects] 223 * Return the name we have for this object in the [Serialization.namedObjects]
224 * collection. 224 * collection.
225 */ 225 */
226 nameFor(object) => serialization._nameFor(object); 226 String nameFor(object) => serialization._nameFor(object);
227 227
228 // For debugging/testing purposes. Find what state a reference points to. 228 // For debugging/testing purposes. Find what state a reference points to.
229 stateForReference(Reference r) => states[r.ruleNumber][r.objectNumber]; 229 stateForReference(Reference r) => states[r.ruleNumber][r.objectNumber];
230 230
231 /** Return the state pointed to by [reference]. */ 231 /** Return the state pointed to by [reference]. */
232 resolveReference(reference) => stateForReference(reference); 232 resolveReference(reference) => stateForReference(reference);
233 } 233 }
234 234
235 /** 235 /**
236 * An abstract class for Reader and Writer, which primarily exists so we can 236 * An abstract class for Reader and Writer, which primarily exists so we can
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 */ 278 */
279 List<List> _data; 279 List<List> _data;
280 280
281 /** 281 /**
282 * The resulting objects, indexed according to the same scheme as 282 * The resulting objects, indexed according to the same scheme as
283 * _data, where each rule has a number, and rules keep track of the objects 283 * _data, where each rule has a number, and rules keep track of the objects
284 * that they serialize, in order. 284 * that they serialize, in order.
285 */ 285 */
286 List<List> objects; 286 List<List> objects;
287 287
288 Format format = new SimpleMapFormat(); 288 final Format format;
289 289
290 /** 290 /**
291 * Creates a new [Reader] that uses the rules from its parent 291 * Creates a new [Reader] that uses the rules from its parent
292 * [Serialization]. Serializations do not keep any state related to 292 * [Serialization]. Serializations do not keep any state related to
293 * a particular read or write operation, so the same one can be used 293 * a particular read or write operation, so the same one can be used
294 * for multiple different Writers/Readers. 294 * for multiple different Writers/Readers.
295 */ 295 */
296 Reader(this.serialization, [Format newFormat]) { 296 Reader(this.serialization, [Format newFormat]) :
297 format = (newFormat == null) ? const SimpleMapFormat() : newFormat {
297 selfDescribing = serialization.selfDescribing; 298 selfDescribing = serialization.selfDescribing;
298 if (newFormat != null) format = newFormat;
299 } 299 }
300 300
301 /** 301 /**
302 * When we read, we may need to look up objects by name in order to link to 302 * When we read, we may need to look up objects by name in order to link to
303 * them. This is particularly true if we have references to classes, 303 * them. This is particularly true if we have references to classes,
304 * functions, mirrors, or other non-portable entities. The map in which we 304 * functions, mirrors, or other non-portable entities. The map in which we
305 * look things up can be provided as an argument to read, but we can also 305 * look things up can be provided as an argument to read, but we can also
306 * provide a map here, and objects will be looked up in both places. 306 * provide a map here, and objects will be looked up in both places.
307 */ 307 */
308 Map namedObjects; 308 Map namedObjects;
(...skipping 13 matching lines...) Expand all
322 322
323 void keyNotFound(key) { 323 void keyNotFound(key) {
324 throw new SerializationException( 324 throw new SerializationException(
325 'Cannot find named object to link to: $key'); 325 'Cannot find named object to link to: $key');
326 } 326 }
327 327
328 /** 328 /**
329 * Return the list of rules to be used when writing. These come from the 329 * Return the list of rules to be used when writing. These come from the
330 * [serialization]. 330 * [serialization].
331 */ 331 */
332 List<SerializationRule> get rules => serialization._rules; 332 List<SerializationRule> get rules => serialization.rules;
333 333
334 /** 334 /**
335 * Internal use only, for testing purposes. Set the data for this reader 335 * Internal use only, for testing purposes. Set the data for this reader
336 * to a List of Lists whose size must match the number of rules. 336 * to a List of Lists whose size must match the number of rules.
337 */ 337 */
338 // When we set the data, initialize the object storage to a matching size. 338 // When we set the data, initialize the object storage to a matching size.
339 void set data(List<List> newData) { 339 void set data(List<List> newData) {
340 _data = newData; 340 _data = newData;
341 objects = _data.map((x) => new List(x.length)).toList(); 341 objects = _data.map((x) => new List(x.length)).toList();
342 } 342 }
(...skipping 24 matching lines...) Expand all
367 rulesWeRead.forEach(serialization.addRule); 367 rulesWeRead.forEach(serialization.addRule);
368 } 368 }
369 } 369 }
370 370
371 /** 371 /**
372 * Inflate all of the objects for [rule]. Does the essential state for all 372 * Inflate all of the objects for [rule]. Does the essential state for all
373 * objects first, then the non-essential state. This avoids cycles in 373 * objects first, then the non-essential state. This avoids cycles in
374 * non-essential state, because all the objects will have already been 374 * non-essential state, because all the objects will have already been
375 * created. 375 * created.
376 */ 376 */
377 inflateForRule(rule) { 377 void inflateForRule(rule) {
378 var dataForThisRule = _data[rule.number]; 378 var dataForThisRule = _data[rule.number];
379 keysAndValues(dataForThisRule).forEach((position, state) { 379 keysAndValues(dataForThisRule).forEach((position, state) {
380 inflateOne(rule, position, state); 380 inflateOne(rule, position, state);
381 }); 381 });
382 keysAndValues(dataForThisRule).forEach((position, state) { 382 keysAndValues(dataForThisRule).forEach((position, state) {
383 rule.inflateNonEssential(state, allObjectsForRule(rule)[position], this); 383 rule.inflateNonEssential(state, allObjectsForRule(rule)[position], this);
384 }); 384 });
385 } 385 }
386 386
387 /** 387 /**
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 435
436 /** Given [rule], return the storage for its objects. */ 436 /** Given [rule], return the storage for its objects. */
437 allObjectsForRule(SerializationRule rule) => objects[rule.number]; 437 allObjectsForRule(SerializationRule rule) => objects[rule.number];
438 438
439 /** Given [reference], return the the state we have stored for it. */ 439 /** Given [reference], return the the state we have stored for it. */
440 _stateFor(Reference reference) => 440 _stateFor(Reference reference) =>
441 _data[reference.ruleNumber][reference.objectNumber]; 441 _data[reference.ruleNumber][reference.objectNumber];
442 442
443 /** Given a reference, return the rule it references. */ 443 /** Given a reference, return the rule it references. */
444 SerializationRule ruleFor(Reference reference) => 444 SerializationRule ruleFor(Reference reference) =>
445 serialization._rules[reference.ruleNumber]; 445 serialization.rules[reference.ruleNumber];
446 446
447 /** 447 /**
448 * Return the primitive rule we are using. This is an ugly mechanism to 448 * Return the primitive rule we are using. This is an ugly mechanism to
449 * support the extra information to reconstruct objects in the 449 * support the extra information to reconstruct objects in the
450 * [SimpleJsonFormat]. 450 * [SimpleJsonFormat].
451 */ 451 */
452 SerializationRule _primitiveRule() { 452 SerializationRule _primitiveRule() {
453 for (var each in rules) { 453 for (var each in rules) {
454 if (each.runtimeType == PrimitiveRule) { 454 if (each.runtimeType == PrimitiveRule) {
455 return each; 455 return each;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 // this as a separate class? 498 // this as a separate class?
499 final Writer writer; 499 final Writer writer;
500 500
501 /** 501 /**
502 * This class works by doing a breadth-first traversal of the objects, 502 * This class works by doing a breadth-first traversal of the objects,
503 * with the traversal order maintained in [queue]. 503 * with the traversal order maintained in [queue].
504 */ 504 */
505 final Queue queue = new Queue(); 505 final Queue queue = new Queue();
506 506
507 /** The root objects from which we will be tracing. */ 507 /** The root objects from which we will be tracing. */
508 List roots = []; 508 final List roots = [];
509 509
510 Trace(this.writer); 510 Trace(this.writer);
511 511
512 addRoot(object) { 512 addRoot(object) {
513 roots.add(object); 513 roots.add(object);
514 } 514 }
515 515
516 /** A convenience method to add a single root and trace it in one step. */ 516 /** A convenience method to add a single root and trace it in one step. */
517 trace(object) { 517 trace(object) {
518 addRoot(object); 518 addRoot(object);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 */ 578 */
579 inflated() => parent.resolveReference(this); 579 inflated() => parent.resolveReference(this);
580 580
581 /** 581 /**
582 * Convert the reference to a map in JSON format. This is specific to the 582 * Convert the reference to a map in JSON format. This is specific to the
583 * custom JSON format we define, and must be consistent with the 583 * custom JSON format we define, and must be consistent with the
584 * [Reader.asReference] method. 584 * [Reader.asReference] method.
585 */ 585 */
586 // TODO(alanknight): This is a hack both in defining a toJson specific to a 586 // TODO(alanknight): This is a hack both in defining a toJson specific to a
587 // particular representation, and the use of a bogus sentinel "__Ref" 587 // particular representation, and the use of a bogus sentinel "__Ref"
588 toJson() => { 588 Map<String, dynamic> toJson() => {
589 "__Ref" : true, 589 "__Ref" : true,
590 "rule" : ruleNumber, 590 "rule" : ruleNumber,
591 "object" : objectNumber 591 "object" : objectNumber
592 }; 592 };
593 593
594 /** Write our information to [list]. Useful in writing to flat formats.*/ 594 /** Write our information to [list]. Useful in writing to flat formats.*/
595 writeToList(List list) { 595 void writeToList(List list) {
596 list.add(ruleNumber); 596 list.add(ruleNumber);
597 list.add(objectNumber); 597 list.add(objectNumber);
598 } 598 }
599 599
600 toString() => "Reference($ruleNumber, $objectNumber)"; 600 String toString() => "Reference($ruleNumber, $objectNumber)";
601 } 601 }
602 602
603 /** 603 /**
604 * This is used during tracing to indicate that an object should be processed 604 * This is used during tracing to indicate that an object should be processed
605 * using a particular rule, rather than the one that might ordinarily be 605 * using a particular rule, rather than the one that might ordinarily be
606 * found for it. This normally only makes sense if the object is uniquely 606 * found for it. This normally only makes sense if the object is uniquely
607 * referenced, and is a more or less internal collection. See ListRuleEssential 607 * referenced, and is a more or less internal collection. See ListRuleEssential
608 * for an example. It knows how to return its object and how to filter. 608 * for an example. It knows how to return its object and how to filter.
609 */ 609 */
610 class DesignatedRuleForObject { 610 class DesignatedRuleForObject {
611 Function rulePredicate; 611 final Function rulePredicate;
612 final target; 612 final target;
613 613
614 DesignatedRuleForObject(this.target, this.rulePredicate); 614 DesignatedRuleForObject(this.target, this.rulePredicate);
615 615
616 possibleRules(List rules) => rules.where(rulePredicate).toList(); 616 List possibleRules(List rules) => rules.where(rulePredicate).toList();
617 } 617 }
OLDNEW
« no previous file with comments | « pkg/serialization/lib/src/format.dart ('k') | pkg/serialization/lib/src/serialization_rule.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698