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

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

Issue 14566015: Change default format to produce output that can be passed between isolates (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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
« no previous file with comments | « no previous file | pkg/serialization/lib/src/reader_writer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 8
9 const Format(); 9 const Format();
10 10
(...skipping 18 matching lines...) Expand all
29 29
30 /** 30 /**
31 * Read the data from [input] in the context of [reader] and return it as a 31 * Read the data from [input] in the context of [reader] and return it as a
32 * Map with entries for "roots", "data" and "rules", which the reader knows 32 * Map with entries for "roots", "data" and "rules", which the reader knows
33 * how to interpret. The type of [input] will depend on the particular format. 33 * how to interpret. The type of [input] will depend on the particular format.
34 */ 34 */
35 Map<String, dynamic> read(input, Reader reader); 35 Map<String, dynamic> read(input, Reader reader);
36 } 36 }
37 37
38 /** 38 /**
39 * A format that stores the data in maps which are converted into a JSON 39 * This is the most basic format, which provides the internal representation
40 * string. Note that the maps aren't nested, and it handles cyclic references 40 * of the serialization, exposing the Reference objects.
41 * by converting object references to [Reference] objects. If you want simple
42 * acyclic JSON look at [SimpleJsonFormat].
43 */ 41 */
44 class SimpleMapFormat extends Format { 42 class InternalMapFormat extends Format {
45 43 const InternalMapFormat();
46 const SimpleMapFormat();
47 44
48 /** 45 /**
49 * Generate output for this format from [w] and return it as a String which 46 * Generate output for this format from [w] and return it as a nested Map
50 * is the [json] representation of a nested Map structure. The top level has 47 * structure. The top level has
51 * 3 fields, "rules" which may hold a definition of the rules used, 48 * 3 fields, "rules" which may hold a definition of the rules used,
52 * "data" which holds the serialized data, and "roots", which holds 49 * "data" which holds the serialized data, and "roots", which holds
53 * [Reference] objects indicating the root objects. Note that roots are 50 * [Reference] objects indicating the root objects. Note that roots are
54 * necessary because the data is organized in the same way as the object 51 * necessary because the data is not organized in the same way as the object
55 * structure, it's a list of lists holding self-contained maps which only 52 * structure, it's a list of lists holding self-contained maps which only
56 * refer to other parts via [Reference] objects. 53 * refer to other parts via [Reference] objects.
57 * This effectively defines a custom JSON serialization format, although
58 * the details of the format vary depending which rules were used.
59 */ 54 */
60 Map<String, dynamic> generateOutput(Writer w) { 55 Map<String, dynamic> generateOutput(Writer w) {
61 var result = { 56 var result = {
62 "rules" : w.serializedRules(), 57 "rules" : w.serializedRules(),
63 "data" : w.states, 58 "data" : w.states,
64 "roots" : w._rootReferences() 59 "roots" : w._rootReferences()
65 }; 60 };
66 return result; 61 return result;
67 } 62 }
68 63
69 /** 64 /**
70 * Read a [json] compatible representation of serialized data in this format 65 * Read serialized data written from this format
71 * and return the nested Map representation described in [generateOutput]. If 66 * and return the nested Map representation described in [generateOutput]. If
72 * the data also includes rule definitions, then these will replace the rules 67 * the data also includes rule definitions, then these will replace the rules
73 * in the [Serialization] for [reader]. 68 * in the [Serialization] for [reader].
74 */ 69 */
75 Map<String, dynamic> read(topLevel, Reader reader) { 70 Map<String, dynamic> read(topLevel, Reader reader) {
76 var ruleString = topLevel["rules"]; 71 var ruleString = topLevel["rules"];
77 reader.readRules(ruleString); 72 reader.readRules(ruleString);
73 reader._data = topLevel["data"];
74 topLevel["roots"] = topLevel["roots"];
78 return topLevel; 75 return topLevel;
79 } 76 }
80 } 77 }
78
79
80 /**
81 * A format that stores the data in maps which can be converted into a JSON
82 * string or passed through an isolate. Note that this consists of maps, but
83 * that they don't follow the original object structure or look like the nested
84 * maps of a [json] representation. They are flat, and [Reference] objects
85 * are converted into a map form that will not make sense to
86 * anything but this format. For simple acyclic JSON that other programs
87 * can read, use [SimpleJsonFormat]. This is the default format, and is
88 * easier to read than the more efficient [SimpleFlatFormat].
89 */
90 class SimpleMapFormat extends InternalMapFormat {
91
92 const SimpleMapFormat();
93
94 /**
95 * Generate output for this format from [w] and return it as a String which
96 * is the [json] representation of a nested Map structure. The top level has
97 * 3 fields, "rules" which may hold a definition of the rules used,
98 * "data" which holds the serialized data, and "roots", which holds
99 * [Reference] objects indicating the root objects. Note that roots are
100 * necessary because the data is not organized in the same way as the object
101 * structure, it's a list of lists holding self-contained maps which only
102 * refer to other parts via [Reference] objects.
103 * This effectively defines a custom JSON serialization format, although
104 * the details of the format vary depending which rules were used.
105 */
106 Map<String, dynamic> generateOutput(Writer w) {
107 forAllStates(w, (x) => x is Reference, referenceToMap);
108 var result = super.generateOutput(w);
109 result["roots"] = result["roots"].map(
110 (x) => x is Reference ? referenceToMap(x) : x).toList();
111 return result;
112 }
113
114 /**
115 * Convert the data generated by the rules to have maps with the fields
116 * of [Reference] objects instead of the [Reference] so that the structure
117 * can be serialized between isolates and json easily.
118 */
119 forAllStates(ReaderOrWriter w, Function predicate, Function transform) {
Jennifer Messerly 2013/05/14 00:21:39 more precise types for the function args? e.g.
120 for (var eachRule in w.rules) {
121 var ruleData = w.states[eachRule.number];
122 for (var data in ruleData) {
123 keysAndValues(data).forEach((key, value) {
124 if (predicate(value)) {
Jennifer Messerly 2013/05/14 00:21:39 -2 indent here. Since it's a function, usually is
125 data[key] = transform(value);
126 }
127 });
128 }
129 }
130 }
131
132 /** Convert the reference to a [json] serializable form. */
133 Map<String, int> referenceToMap(Reference ref) => ref == null ? null :
134 {
135 "__Ref" : 0,
136 "rule" : ref.ruleNumber,
137 "object" : ref.objectNumber
138 };
139
140 /**
141 * Convert the [referenceToMap] form for a reference back to a [Reference]
142 * object.
143 */
144 Reference mapToReference(ReaderOrWriter parent, Map<String, int> ref) =>
145 ref == null ? null : new Reference(parent, ref["rule"], ref["object"]);
146
147 /**
148 * Read serialized data written in this format
149 * and return the nested Map representation described in [generateOutput]. If
150 * the data also includes rule definitions, then these will replace the rules
151 * in the [Serialization] for [reader].
152 */
153 Map<String, dynamic> read(topLevel, Reader reader) {
154 super.read(topLevel, reader);
155 forAllStates(reader,
156 (ref) => ref is Map && ref["__Ref"] != null,
157 (ref) => mapToReference(reader, ref));
158 topLevel["roots"] = topLevel["roots"]
159 .map((x) => x is Map<String, int> ? mapToReference(reader, x) : x)
160 .toList();
161 return topLevel;
162 }
163 }
81 164
82 /** 165 /**
83 * A format for "normal" [json] representation of objects. It stores 166 * A format for "normal" [json] representation of objects. It stores
84 * the fields of the objects as nested maps, and doesn't allow cycles. This can 167 * the fields of the objects as nested maps, and doesn't allow cycles. This can
85 * be useful in talking to existing APIs that expect [json] format data. The 168 * be useful in talking to existing APIs that expect [json] format data. The
86 * output will be either a simple object (string, num, bool), a List, or a Map, 169 * output will be either a simple object (string, num, bool), a List, or a Map,
87 * with nesting of those. 170 * with nesting of those.
88 * Note that since the classes of objects aren't normally stored, this isn't 171 * Note that since the classes of objects aren't normally stored, this isn't
89 * enough information to read back the objects. However, if the 172 * enough information to read back the objects. However, if the
90 * If the [storeRoundTripInfo] field of the format is set to true, then this 173 * If the [storeRoundTripInfo] field of the format is set to true, then this
91 * will store the rule number along with the data, allowing reconstruction. 174 * will store the rule number along with the data, allowing reconstruction.
92 */ 175 */
93 class SimpleJsonFormat extends Format { 176 class SimpleJsonFormat extends SimpleMapFormat {
94 177
95 /** 178 /**
96 * Indicate if we should store rule numbers with map/list data so that we 179 * Indicate if we should store rule numbers with map/list data so that we
97 * will know how to reconstruct it with a read operation. If we don't, this 180 * will know how to reconstruct it with a read operation. If we don't, this
98 * will be more compliant with things that expect known format JSON as input, 181 * will be more compliant with things that expect known format JSON as input,
99 * but we won't be able to read back the objects. 182 * but we won't be able to read back the objects.
100 */ 183 */
101 final bool storeRoundTripInfo; 184 final bool storeRoundTripInfo;
102 185
103 /** 186 /**
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 return new Reference(r, a, b); 552 return new Reference(r, a, b);
470 } 553 }
471 } 554 }
472 555
473 /** Return the next element from the input. */ 556 /** Return the next element from the input. */
474 _next(Iterator input) { 557 _next(Iterator input) {
475 input.moveNext(); 558 input.moveNext();
476 return input.current; 559 return input.current;
477 } 560 }
478 } 561 }
OLDNEW
« no previous file with comments | « no previous file | pkg/serialization/lib/src/reader_writer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698