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

Unified Diff: pkg/serialization/lib/src/reader_writer.dart

Issue 11820032: Make input/output formats pluggable, adapt to new libraries (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Changes from review comments Created 7 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: pkg/serialization/lib/src/reader_writer.dart
diff --git a/pkg/serialization/lib/src/reader_writer.dart b/pkg/serialization/lib/src/reader_writer.dart
index 8892aa716985fbd0e243f91602c9f9c796f43286..87535cea9173d849e3fb46234263281496b90afd 100644
--- a/pkg/serialization/lib/src/reader_writer.dart
+++ b/pkg/serialization/lib/src/reader_writer.dart
@@ -31,6 +31,8 @@ class Writer {
*/
bool selfDescribing;
+ Format format = new SimpleMapFormat();
+
/**
* Objects that cannot be represented in-place in the serialized form need
* to have references to them stored. The [Reference] objects are computed
@@ -59,69 +61,21 @@ class Writer {
* related to a particular read/write, so the same one can be used
* for multiple different Readers/Writers.
*/
- Writer(this.serialization) {
+ Writer(this.serialization, [Format newFormat]) {
trace = new Trace(this);
selfDescribing = serialization.selfDescribing;
+ if (newFormat != null) format = newFormat;
}
/**
* This is the main API for a [Writer]. It writes the objects and returns
- * the serialized representation, currently a JSON format of a map
- * whose data is either lists indexed by field position or maps indexed
- * by field name, and holding either primitives or references. See [toMaps]
+ * the serialized representation, as determined by [format].
*/
- // TODO(alanknight): Generalize the output representation. Probably requires
- // introducing some sort of OutputFormat object.
- String write(anObject) {
+ write(anObject) {
trace.addRoot(anObject);
trace.traceAll();
_flatten();
- return toStringFormat();
- }
-
- /**
- * This is an alternate writing API that writes the objects and returns
- * the serialized representation as a List of simple objects.
- * See [toFlatFormat].
- */
- List writeFlat(anObject) {
- shouldUseReferencesForPrimitives = true;
- trace.addRoot(anObject);
- trace.traceAll();
- _flatten();
- return toFlatFormat();
- }
-
- /**
- * Write to a simple flat format. This format is at the proof of concept
- * stage, so details are not finalized and are likely to change in the future.
- * Right now this produces a List containing null, int, and String. This is
- * more space-efficient than the map format created by [toStringFormat] or
- * [toMaps], but is much less human-readable.
- */
- List toFlatFormat() {
- var result = new List(3);
- // TODO(alanknight): Don't make it call toMaps in order to make non-maps.
- // As part of that, if writing flat, the rule serialization should be flat.
- var stuff = toMaps();
- result[0] = stuff["rules"];
- var roots = new List();
- stuff["roots"].forEach((x) => x.writeToList(roots));
- result[2] = roots;
-
- // TODO(alanknight): This needs serious generalization. Do we introduce
- // an output format object that the rules talk to? Do we make use of the
- // fact that rules talk to something that looks to them like a List. Do
- // we then mandate that instead of saying they have complete charge of
- // their own storage?
- var flatData = [];
- for (var eachRule in rules) {
- var ruleData = stuff["data"][eachRule.number];
- flatData.add(ruleData.length);
- eachRule.dumpStateInto(ruleData, flatData);
- }
- result[1] = flatData;
- return result;
+ return format.generateOutput(this);
}
/**
@@ -174,7 +128,20 @@ class Writer {
* That depends on which format we're using, so a flat format will want
* references, but the Map format can store them directly.
*/
- bool shouldUseReferencesForPrimitives = false;
+ bool get shouldUseReferencesForPrimitives
+ => format.shouldUseReferencesForPrimitives;
+
+ /**
+ * Returns a serialized version of the [SerializationRule]s used to write
+ * the data, if [selfDescribing] is true, otherwise returns null.
+ */
+ serializedRules() {
+ if (!selfDescribing) return null;
+ var meta = serialization.ruleSerialization();
+ var writer = new Writer(meta);
+ writer.selfDescribing = false;
+ return writer.write(serialization._rules);
+ }
/** Record a [state] entry for a particular rule. */
void _addStateForRule(eachRule, state) {
@@ -222,45 +189,10 @@ class Writer {
}
/**
- * Return the serialized data in string format. Currently hard-coded to
- * our custom JSON format.
- */
- String toStringFormat() {
- return json.stringify(toMaps());
- }
-
- /**
- * Returns the full serialized structure as nested maps. The top-level
- * has 3 fields, "rules" which may hold a definition of the rules used,
- * "data" which holds the serialized data, and "roots", which holds
- * [Reference] objects indicating the root objects. Note that roots are
- * necessary because the data is organized in the same way as the object
- * structure, it's a list of lists holding self-contained maps which only
- * refer to other parts via [Reference] objects.
- * This effectively defines a custom JSON serialization format, although
- * the details of the format vary depending which rules were used.
- */
- Map toMaps() {
- var result = new Map();
- var savedRules;
- if (selfDescribing) {
- var meta = serialization._ruleSerialization();
- var writer = new Writer(meta);
- writer.selfDescribing = false;
- savedRules = writer.write(serialization._rules);
- }
- result["rules"] = savedRules;
- result["data"] = states;
- result["roots"] = _rootReferences(trace.roots);
- return result;
- }
-
- /**
* Return a list of [Reference] objects pointing to our roots. This will be
* stored in the output under "roots" in the default format.
*/
- _rootReferences(roots) =>
- roots.mappedBy(_referenceFor).toList();
+ _rootReferences() => trace.roots.mappedBy(_referenceFor).toList();
/**
* Given an object, return a reference for it if one exists. If there's
@@ -324,14 +256,17 @@ class Reader {
*/
List<List> objects;
+ Format format = new SimpleMapFormat();
+
/**
* Creates a new [Reader] that uses the rules from its parent
* [Serialization]. Serializations do not keep any state related to
* a particular read or write operation, so the same one can be used
* for multiple different Writers/Readers.
*/
- Reader(this.serialization) {
+ Reader(this.serialization, [Format newFormat]) {
selfDescribing = serialization.selfDescribing;
+ if (newFormat != null) format = newFormat;
}
/**
@@ -374,28 +309,24 @@ class Reader {
/**
* This is the primary method for a [Reader]. It takes the input data,
- * currently hard-coded to expect our custom JSON format, and returns
- * the root object.
+ * decodes it according to [format] and returns the root object.
*/
- read(String input, [Map externals = const {}]) {
+ read(rawInput, [Map externals = const {}]) {
namedObjects = externals;
- var topLevel = json.parse(input);
- var ruleString = topLevel["rules"];
- readRules(ruleString, externals);
- data = topLevel["data"];
+ var input = format.read(rawInput, this);
+ data = input["data"];
rules.forEach(inflateForRule);
- var roots = topLevel["roots"];
- return inflateReference(roots.first);
+ return inflateReference(input["roots"].first);
}
/**
* If the data we are reading from has rules written to it, read them back
* and set them as the rules we will use.
*/
- void readRules(String newRules, Map externals) {
+ void readRules(String newRules) {
// TODO(alanknight): Replacing the serialization is kind of confusing.
List rulesWeRead = (newRules == null) ?
- null : serialization._ruleSerialization().read(newRules, externals);
+ null : serialization.ruleSerialization().read(newRules, namedObjects);
if (rulesWeRead != null && !rulesWeRead.isEmpty) {
serialization = new Serialization.blank();
rulesWeRead.forEach(serialization.addRule);
@@ -403,41 +334,6 @@ class Reader {
}
/**
- * This is a hard-coded read method for a vaguely flat format. It's just a
- * proof of concept of handling more flat formats right now, and needs a lot
- * of fixing and generalization.
- */
- readFlat(List input, [Map externals = const {}]) {
- // TODO(alanknight): Way too much code duplication with read. Numerous
- // code smells.
- namedObjects = externals;
- var topLevel = input;
- var ruleString = topLevel[0];
- readRules(ruleString, externals);
- var flatData = topLevel[1];
- var stream = flatData.iterator;
- var tempData = new List(rules.length);
- for (var eachRule in rules) {
- tempData[eachRule.number] = eachRule.pullStateFrom(stream);
- }
- data = tempData;
- for (var eachRule in rules) {
- inflateForRule(eachRule);
- }
- var rootsAsInts = topLevel[2];
- var rootStream = rootsAsInts.iterator;
- var roots = new List();
- while (rootStream.moveNext()) {
- var first = rootStream.current;
- rootStream.moveNext();
- var second = rootStream.current;
- roots.add(new Reference(this, first, second));
- }
- var x = inflateReference(roots[0]);
- return inflateReference(roots.first);
- }
-
- /**
* Inflate all of the objects for [rule]. Does the essential state for all
* objects first, then the non-essential state. This avoids cycles in
* non-essential state, because all the objects will have already been
@@ -511,6 +407,20 @@ class Reader {
serialization._rules[reference.ruleNumber];
/**
+ * Return the primitive rule we are using. This is an ugly mechanism to
+ * support the extra information to reconstruct objects in the
+ * [SimpleJsonFormat].
+ */
+ SerializationRule _primitiveRule() {
+ for (var each in rules) {
+ if (each.runtimeType == PrimitiveRule) {
+ return each;
+ }
+ }
+ throw new SerializationException("No PrimitiveRule found");
+ }
+
+ /**
* Given a possible reference [anObject], call either [ifReference] or
* [ifNotReference], depending if it's a reference or not. This is the
* primary place that knows about the serialized representation of a
@@ -634,6 +544,8 @@ class Reference {
list.add(ruleNumber);
list.add(objectNumber);
}
+
+ toString() => "Reference $ruleNumber, $objectNumber";
}
/**
« no previous file with comments | « pkg/serialization/lib/src/mirrors_helpers.dart ('k') | pkg/serialization/lib/src/serialization_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698