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

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

Issue 12136002: Some fixes to work better with the services framework (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Serialization updates to work more nicely with services framework Created 7 years, 10 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 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 * Return true if this format stores primitives in their own area and uses 9 * Return true if this format stores primitives in their own area and uses
10 * references to them (e.g. [SimpleFlatFormat]) and false if primitives 10 * references to them (e.g. [SimpleFlatFormat]) and false if primitives
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 * is the [json] representation of a nested Map structure. The top level has 45 * 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, 46 * 3 fields, "rules" which may hold a definition of the rules used,
47 * "data" which holds the serialized data, and "roots", which holds 47 * "data" which holds the serialized data, and "roots", which holds
48 * [Reference] objects indicating the root objects. Note that roots are 48 * [Reference] objects indicating the root objects. Note that roots are
49 * necessary because the data is organized in the same way as the object 49 * 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 50 * structure, it's a list of lists holding self-contained maps which only
51 * refer to other parts via [Reference] objects. 51 * refer to other parts via [Reference] objects.
52 * This effectively defines a custom JSON serialization format, although 52 * This effectively defines a custom JSON serialization format, although
53 * the details of the format vary depending which rules were used. 53 * the details of the format vary depending which rules were used.
54 */ 54 */
55 String generateOutput(Writer w) { 55 generateOutput(Writer w) {
justinfagnani 2013/02/09 21:21:56 Style nit: Why remove the type here? Since the met
Jennifer Messerly 2013/02/10 00:20:35 Style nit nit :) If return type is "dynamic", we
Alan Knight 2013/02/11 23:38:42 Good point, changed this to return Map<String, dyn
56 var result = { 56 var result = {
57 "rules" : w.serializedRules(), 57 "rules" : w.serializedRules(),
58 "data" : w.states, 58 "data" : w.states,
59 "roots" : w._rootReferences() 59 "roots" : w._rootReferences()
60 }; 60 };
61 return json.stringify(result); 61 return result;
62 } 62 }
63 63
64 /** 64 /**
65 * Read a [json] encoded string representing serialized data in this format 65 * Read a [json] compatible representation of serialized data in this format
66 * and return the nested Map representation described in [generateOutput]. If 66 * and return the nested Map representation described in [generateOutput]. If
67 * 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
68 * in the [Serialization] for [reader]. 68 * in the [Serialization] for [reader].
69 */ 69 */
70 Map<String, dynamic> read(String input, Reader reader) { 70 Map<String, dynamic> read(topLevel, Reader reader) {
71 var topLevel = json.parse(input);
72 var ruleString = topLevel["rules"]; 71 var ruleString = topLevel["rules"];
73 reader.readRules(ruleString); 72 reader.readRules(ruleString);
74 return topLevel; 73 return topLevel;
75 } 74 }
76 } 75 }
77 76
78 /** 77 /**
79 * A format for "normal" JSON representation of objects. It stores 78 * A format for "normal" JSON representation of objects. It stores
80 * the fields of the objects as nested maps, and doesn't allow cycles. This can 79 * the fields of the objects as nested maps, and doesn't allow cycles. This can
81 * be useful in talking to existing APIs that expect JSON format data. However, 80 * be useful in talking to existing APIs that expect JSON format data. However,
(...skipping 14 matching lines...) Expand all
96 final bool storeRoundTripInfo; 95 final bool storeRoundTripInfo;
97 96
98 /** 97 /**
99 * If we store the rule numbers, what key should we use to store them. 98 * If we store the rule numbers, what key should we use to store them.
100 */ 99 */
101 String ruleIdentifier = "__rule"; 100 String ruleIdentifier = "__rule";
102 101
103 SimpleJsonFormat({this.storeRoundTripInfo : false}); 102 SimpleJsonFormat({this.storeRoundTripInfo : false});
104 103
105 /** 104 /**
106 * Generate output for this format from [w] and return it as a String which 105 * Generate output for this format from [w] and return it as
107 * is the [json] representation of a nested Map structure. 106 * the [json] representation of a nested Map structure.
108 */ 107 */
109 String generateOutput(Writer w) { 108 generateOutput(Writer w) {
justinfagnani 2013/02/09 21:21:56 Map as the return type?
Jennifer Messerly 2013/02/10 00:20:35 I don't think it necessarily returns a map if not
Alan Knight 2013/02/11 23:38:42 It doesn't necessarily return a Map, part of the c
110 jsonify(w); 109 jsonify(w);
111 return json.stringify(w.stateForReference(w._rootReferences().first)); 110 var root = w._rootReferences().first;
111 if (root is Reference) root = w.stateForReference(root);
112 if (w.selfDescribing && storeRoundTripInfo) {
113 root = {
114 "rules" : w.serializedRules(),
Jennifer Messerly 2013/02/08 04:04:38 I think I usually just indent this +2, since it ha
Alan Knight 2013/02/11 23:38:42 Because I made those be identifiers rather than li
115 "data" : root
116 };
117 }
118 return root;
112 } 119 }
113 120
114 /** 121 /**
115 * Convert the data generated by the rules to have nested maps instead 122 * Convert the data generated by the rules to have nested maps instead
116 * of Reference objects and to add rule numbers if [storeRoundTripInfo] 123 * of Reference objects and to add rule numbers if [storeRoundTripInfo]
117 * is true. 124 * is true.
118 */ 125 */
119 jsonify(Writer w) { 126 jsonify(Writer w) {
120 for (var eachRule in w.rules) { 127 for (var eachRule in w.rules) {
121 var ruleData = w.states[eachRule.number]; 128 var ruleData = w.states[eachRule.number];
(...skipping 21 matching lines...) Expand all
143 * For one particular entry, which is either a Map or a List, update it 150 * For one particular entry, which is either a Map or a List, update it
144 * to turn References into a nested List/Map. 151 * to turn References into a nested List/Map.
145 */ 152 */
146 jsonifyEntry(map, Writer w) { 153 jsonifyEntry(map, Writer w) {
147 keysAndValues(map).forEach((key, value) { 154 keysAndValues(map).forEach((key, value) {
148 if (value is Reference) map[key] = w.stateForReference(value); 155 if (value is Reference) map[key] = w.stateForReference(value);
149 }); 156 });
150 } 157 }
151 158
152 /** 159 /**
153 * Read a [json] encoded string representing serialized data in this format 160 * Read a [json] encoded string representing serialized data in this format
justinfagnani 2013/02/09 21:21:56 string->?
Alan Knight 2013/02/11 23:38:42 Done.
154 * and return the Map representation that the reader expects, with top-level 161 * and return the Map representation that the reader expects, with top-level
155 * entries for "rules", "data", and "roots". Nested lists/maps will be 162 * entries for "rules", "data", and "roots". Nested lists/maps will be
156 * converted into Reference objects. Note that if the data was not written 163 * converted into Reference objects. Note that if the data was not written
157 * with [storeRoundTripInfo] true this will fail. 164 * with [storeRoundTripInfo] true this will fail.
158 */ 165 */
159 Map<String, dynamic> read(String input, Reader r) { 166 Map<String, dynamic> read(data, Reader reader) {
160 var data = json.parse(input); 167 var result = new Map();
161 var result = {}; 168 bool looksLikeItHasOurExtraData = data is Map &&
162 result["rules"] = null; 169 data.containsKey("rules") && data.containsKey("data");
163 var ruleData = 170 var rules = looksLikeItHasOurExtraData ? data["rules"] : null;
164 new List(r.serialization.rules.length).map((x) => []).toList(); 171 reader.readRules(rules);
justinfagnani 2013/02/09 21:21:56 what happens here if "rules" is just some user dat
Jennifer Messerly 2013/02/10 00:20:35 This is a good idea. We should go even further IM
Alan Knight 2013/02/11 23:38:42 OK, I changed this to just look at the "selfDescri
165 var top = recursivelyFixUp(data, r, ruleData); 172 var ruleData = new List(reader.serialization.rules.length).
173 map((x) => []).toList();
174 // If our result was a map with rules and data, get the data part. Otherwise
175 // assume that the whole thing is the data.
176 var actualData = (rules == null) ? data : data["data"];
177 var top = recursivelyFixUp(actualData, reader, ruleData);
166 result["data"] = ruleData; 178 result["data"] = ruleData;
167 result["roots"] = [top]; 179 result["roots"] = [top];
168 return result; 180 return result;
169 } 181 }
170 182
171 /** 183 /**
172 * Convert nested references in [data] into [Reference] objects. 184 * Convert nested references in [data] into [Reference] objects.
173 */ 185 */
174 recursivelyFixUp(data, Reader r, List result) { 186 recursivelyFixUp(input, Reader r, List result) {
187 var data = input;
175 if (isPrimitive(data)) { 188 if (isPrimitive(data)) {
176 result[r._primitiveRule().number].add(data); 189 result[r._primitiveRule().number].add(data);
177 return data; 190 return data;
178 } 191 }
179 var ruleNumber; 192 var ruleNumber;
193 // If we've added the rule number on as the last item in a list we have
194 // to get rid of it or it will be interpreted as extra data. For a map
195 // the library will be ok, but we need to get rid of the extra key before
196 // the data is shown to the user, so we destructively modify.
180 if (data is List) { 197 if (data is List) {
181 ruleNumber = data.removeLast(); 198 ruleNumber = data.last;
199 data = data.take(data.length -1);
182 } else if (data is Map) { 200 } else if (data is Map) {
183 ruleNumber = data.remove(ruleIdentifier); 201 ruleNumber = data.remove(ruleIdentifier);
184 } else { 202 } else {
185 throw new SerializationException("Invalid data format"); 203 throw new SerializationException("Invalid data format");
186 } 204 }
187 var newData = mapValues(data, (x) => recursivelyFixUp(x, r, result)); 205 // Do not use mappedBy or other lazy operations for this. They do not play
206 // well with a function that destructively modifies its arguments.
207 var newData = mapValues(data, (each) => recursivelyFixUp(each, r, result));
188 result[ruleNumber].add(newData); 208 result[ruleNumber].add(newData);
189 return new Reference(r, ruleNumber, result[ruleNumber].length - 1); 209 return new Reference(r, ruleNumber, result[ruleNumber].length - 1);
190 } 210 }
191 } 211 }
192 212
193 /** 213 /**
194 * Writes to a simple mostly-flat format. Details are subject to change. 214 * Writes to a simple mostly-flat format. Details are subject to change.
195 * Right now this produces a List containing null, num, and String. This is 215 * Right now this produces a List containing null, num, and String. This is
196 * more space-efficient than the map formats, but much less human-readable. 216 * more space-efficient than the map formats, but much less human-readable.
197 * Simple usage is to turn this into JSON for transmission. 217 * Simple usage is to turn this into JSON for transmission.
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 return new Reference(r, a, b); 448 return new Reference(r, a, b);
429 } 449 }
430 } 450 }
431 451
432 /** Return the next element from the input. */ 452 /** Return the next element from the input. */
433 _next(Iterator input) { 453 _next(Iterator input) {
434 input.moveNext(); 454 input.moveNext();
435 return input.current; 455 return input.current;
436 } 456 }
437 } 457 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698