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 87535cea9173d849e3fb46234263281496b90afd..88488852ce8fbcec9d74ecae82cb02a5615366b2 100644 |
--- a/pkg/serialization/lib/src/reader_writer.dart |
+++ b/pkg/serialization/lib/src/reader_writer.dart |
@@ -13,7 +13,7 @@ part of serialization; |
// that isn't necessary, e.g. detecting cycles and maintaining references. |
// Consider having an abstract superclass with the basic functionality and |
// simple serialization subclasses where we know there aren't cycles. |
-class Writer { |
+class Writer implements ReaderOrWriter { |
/** |
* The [serialization] holds onto the rules that define how objects |
* are serialized. |
@@ -88,8 +88,13 @@ class Writer { |
for (var eachRule in rules) { |
_growStates(eachRule); |
var index = eachRule.number; |
- for (var eachState in states[index]) { |
- eachRule.flatten(eachState, this); |
+ var statesForThisRule = states[index]; |
+ for (var i = 0; i < statesForThisRule.length; i++) { |
+ var eachState = statesForThisRule[i]; |
+ var newState = eachRule.flatten(eachState, this); |
+ if (newState != null) { |
+ statesForThisRule[i] = newState; |
+ } |
} |
} |
} |
@@ -196,11 +201,14 @@ class Writer { |
/** |
* Given an object, return a reference for it if one exists. If there's |
- * no reference, return null. Once we have finished the tracing step, all |
- * objects that should have a reference (roughly speaking, non-primitives) |
- * can be relied on to have a reference. |
+ * no reference, return the object itself. Once we have finished the tracing |
+ * step, all objects that should have a reference (roughly speaking, |
+ * non-primitives) can be relied on to have a reference. |
*/ |
- _referenceFor(object) => references[object]; |
+ _referenceFor(object) { |
+ var result = references[object]; |
+ return (result == null) ? object : result; |
+ } |
/** |
* Return true if the [namedObjects] collection has a reference to [object]. |
@@ -217,13 +225,32 @@ class Writer { |
// For debugging/testing purposes. Find what state a reference points to. |
stateForReference(Reference r) => states[r.ruleNumber][r.objectNumber]; |
+ |
+ /** Return the state pointed to by [reference]. */ |
+ resolveReference(reference) => stateForReference(reference); |
+} |
+ |
+/** |
+ * An abstract class for Reader and Writer, which primarily exists so we can |
+ * type things that will refer to one or the other, depending on which |
+ * operation we're doing. |
+ */ |
+abstract class ReaderOrWriter { |
+ /** Return the list of serialization rules we are using.*/ |
+ List<SerializationRule> get rules; |
+ |
+ /** |
+ * Return the object, or state, that ref points to, depending on which |
+ * we're generating. |
+ */ |
+ resolveReference(Reference ref); |
} |
/** |
* The main class responsible for reading. It holds |
* onto the necessary state and to the objects that have been inflated. |
*/ |
-class Reader { |
+class Reader implements ReaderOrWriter { |
/** |
* The serialization that specifies how we read. Note that in contrast |
@@ -388,6 +415,9 @@ class Reader { |
}); |
} |
+ /** Return the object pointed to by [reference]. */ |
+ resolveReference(reference) => inflateReference(reference); |
+ |
/** |
* Given [reference], return what we have stored as an object for it. Note |
* that, depending on the current state, this might be null or a Sentinel. |
@@ -518,13 +548,27 @@ class Trace { |
*/ |
class Reference { |
/** The [Reader] or [Writer] that owns this reference. */ |
- final parent; |
+ final ReaderOrWriter parent; |
/** The position of the rule that controls this reference in [parent]. */ |
final int ruleNumber; |
/** The index of the referred-to object in the storage of [parent] */ |
final int objectNumber; |
- const Reference(this.parent, this.ruleNumber, this.objectNumber); |
+ Reference(this.parent, this.ruleNumber, this.objectNumber) { |
+ if (ruleNumber == null || objectNumber == null) { |
+ throw new SerializationException("Invalid Reference"); |
+ } |
+ if (parent.rules.length < ruleNumber) { |
+ throw new SerializationException("Invalid Reference"); |
+ } |
+ } |
+ |
+ /** |
+ * Return the thing this reference points to. Assumes that we have a valid |
+ * parent and that it is a Reader, as inflating is not meaningful when |
+ * writing. |
+ */ |
+ inflated() => parent.resolveReference(this); |
/** |
* Convert the reference to a map in JSON format. This is specific to the |
@@ -545,7 +589,7 @@ class Reference { |
list.add(objectNumber); |
} |
- toString() => "Reference $ruleNumber, $objectNumber"; |
+ toString() => "Reference($ruleNumber, $objectNumber)"; |
} |
/** |