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

Unified Diff: pkg/serialization/lib/src/serialization_rule.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/serialization_rule.dart
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index d0228465d646a8177974e84b0ace1c27d043179c..d9aed0f9b036ae49e1b853f7cc522df9acb3ba33 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -102,90 +102,23 @@ abstract class SerializationRule {
/**
* If we have [object] as part of our state, should we represent that
- * directly, or should we make a reference for it. By default we use a
- * reference for everything.
+ * directly, or should we make a reference for it. By default, true.
+ * This may also delegate to [writer].
*/
- bool shouldUseReferenceFor(object, Writer w) => true;
+ bool shouldUseReferenceFor(object, Writer writer) => true;
/**
- * This writes the data from our internal representation into a List.
- * It is used in order to write to a flat format, and is likely to be
- * folded into a more general mechanism for supporting different output
- * formats.
+ * Return true if the data this rule returns is variable length, so a
+ * length needs to be written for it if the format requires that. Return
+ * false if the results are always the same length.
*/
- // TODO(alanknight): This really shouldn't exist, but is a temporary measure
- // for writing to a a flat format until that's more fleshed out. It takes
- // the internal representation of the rule's state, which is particularly
- // bad. The default implementation treats the ruleData as a List of Lists
- // of references.
- void dumpStateInto(List ruleData, List target) {
- // Needing the intermediate is also bad for performance, but tricky
- // to do otherwise without a mechanism to precalculate the size.
- var intermediate = new List();
- var totalLength = 0;
- for (var eachList in ruleData) {
- if (writeLengthInFlatFormat) {
- intermediate.add(eachList.length);
- }
- for (var eachRef in eachList) {
- if (eachRef == null) {
- intermediate..add(null)..add(null);
- } else {
- eachRef.writeToList(intermediate);
- }
- }
- }
- target.addAll(intermediate);
- }
-
- /**
- * Return true if this rule writes a length value before each entry in
- * the flat format. Return false if the results are fixed length.
- */
- // TODO(alanknight): This should probably go away with more general formats.
- bool get writeLengthInFlatFormat => false;
-
- /**
- * The inverse of dumpStateInto, this reads the rule's state from an
- * iterator in a flat format.
- */
- pullStateFrom(Iterator stream) {
- stream.moveNext();
- var numberOfEntries = stream.current;
- var ruleData = new List();
- for (var i = 0; i < numberOfEntries; i++) {
- var subLength = dataLengthIn(stream);
- var subList = [];
- ruleData.add(subList);
- for (var j = 0; j < subLength; j++) {
- stream.moveNext();
- var a = stream.current;
- stream.moveNext();
- var b = stream.current;
- if (a is! int) {
- // This wasn't a reference, just use the first object as a literal.
- // particularly used for the case of null.
- subList.add(a);
- } else {
- subList.add(new Reference(this, a, b));
- }
- }
- }
- return ruleData;
- }
-
- /**
- * Return the length of the list of data we expect to see on a particular
- * iterator in a flat format. This may have been encoded in the stream if we
- * are variable length, or it may be constant. Returns null if the [Iterator]
- * is empty.
- */
- dataLengthIn(Iterator stream) =>
- writeLengthInFlatFormat ? (stream..moveNext()).current : dataLength;
+ bool get hasVariableLengthEntries => true;
/**
- * If the data is fixed length, return it here. Unused in the non-flat
- * format, or if the data is variable length.
+ * If the data is fixed length, return it here. The format may or may not
+ * make use of this, depending on whether it already has enough information
+ * to determine the length on its own. If [hasVariableLengthEntries] is true
+ * this is ignored.
*/
int get dataLength => 0;
}
@@ -223,49 +156,7 @@ class ListRule extends SerializationRule {
}
}
- /**
- * When reading from a flat format we are given [stream] and need to pull as
- * much data from it as we need. Our format is that we have an integer N
- * indicating the number of objects and then for each object a length M,
- * and then M references, where a reference is stored in the stream as two
- * integers. Or, in the special case of null, two nulls.
- */
- pullStateFrom(Iterator stream) {
- // TODO(alanknight): This is much too close to the basicRule implementation,
- // and I'd refactor them if I didn't think this whole mechanism needed to
- // change soon.
- stream.moveNext();
- var length = stream.current;
- var ruleData = new List();
- for (var i = 0; i < length; i++) {
- stream.moveNext();
- var subLength = stream.current;
- var subList = new List();
- ruleData.add(subList);
- for (var j = 0; j < subLength; j++) {
- stream.moveNext();
- var a = stream.current;
- stream.moveNext();
- var b = stream.current;
- if (!(a is int)) {
- // This wasn't a reference, just use the first object as a literal.
- // particularly used for the case of null.
- subList.add(a);
- } else {
- subList.add(new Reference(this, a, b));
- }
- }
- }
- return ruleData;
- }
-
- /**
- * Return true because we need to write the length of each list in the flat
- * format. */
- bool get writeLengthInFlatFormat => true;
-
- /** Return the length of the next list when reading the flat format. */
- int dataLengthIn(Iterator stream) => stream.next();
+ bool get hasVariableLengthEntries => true;
}
/**
@@ -310,32 +201,7 @@ class PrimitiveRule extends SerializationRule {
bool shouldUseReferenceFor(object, Writer w) =>
w.shouldUseReferencesForPrimitives;
- /**
- * This writes the data from our internal representation into a List.
- * It is used in order to write to a flat format, and is likely to be
- * folded into a more general mechanism for supporting different output
- * formats. For primitives, the ruleData is our list of all the
- * primitives and just add it into the target.
- */
- void dumpStateInto(List ruleData, List target) {
- target.addAll(ruleData);
- }
-
- /**
- * When reading from a flat format we are given [stream] and need to pull as
- * much data from it as we need. Our format is that we have an integer N
- * indicating the number of objects and then N simple objects.
- */
- pullStateFrom(Iterator stream) {
- stream.moveNext();
- var length = stream.current;
- var ruleData = new List();
- for (var i = 0; i < length; i++) {
- stream.moveNext();
- ruleData.add(stream.current);
- }
- return ruleData;
- }
+ bool get hasVariableLengthEntries => false;
}
/** Typedef for the object construction closure used in ClosureRule. */
@@ -491,12 +357,12 @@ abstract class CustomRule extends SerializationRule {
// We don't want to have to make the end user tell us how long the list is
// separately, so write it out for each object, even though they're all
// expected to be the same length.
- get writeLengthInFlatFormat => true;
+ get hasVariableLengthEntries => true;
}
/** Create a lazy list/map that will inflate its items on demand in [r]. */
_lazy(l, Reader r) {
- if (l is List) return l.mappedBy(r.inflateReference);
+ if (l is List) return new _LazyList(l, r);
if (l is Map) return new _LazyMap(l, r);
throw new SerializationException("Invalid type: must be Map or List - $l");
}
@@ -511,8 +377,8 @@ _lazy(l, Reader r) {
class _LazyMap implements Map {
_LazyMap(this._raw, this._reader);
- Map _raw;
- Reader _reader;
+ final Map _raw;
+ final Reader _reader;
// This is the only operation that really matters.
operator [](x) => _reader.inflateReference(_raw[x]);
@@ -524,15 +390,65 @@ class _LazyMap implements Map {
// These operations will work, but may be expensive, and are probably
// best avoided.
- get _inflated => keysAndValues(_raw).map(_reader.inflateReference);
+ get _inflated => keysAndValues(_raw).mappedBy(_reader.inflateReference);
bool containsValue(x) => _inflated.containsValue(x);
Iterable get values => _inflated.values;
void forEach(f) => _inflated.forEach(f);
// These operations are all invalid
- _throw() => throw new UnsupportedError("Not modifiable");
+ _throw() {
+ throw new UnsupportedError("Not modifiable");
+ }
operator []=(x, y) => _throw();
putIfAbsent(x, y) => _throw();
remove(x) => _throw();
clear() => _throw();
}
+
+/**
+ * This provides an implementation of List that wraps a list which may
+ * contain references to (potentially) non-inflated objects. If these
+ * are accessed it will inflate them. This allows us to pass something that
+ * looks like it's just a list of objects to a [CustomRule] without needing
+ * to inflate all the references in advance.
+ */
+class _LazyList extends Iterable implements List {
+ _LazyList(this._raw, this._reader);
+
+ final List _raw;
+ final Reader _reader;
+
+ // This is the only operation that really matters.
+ operator [](x) => _reader.inflateReference(_raw[x]);
+
+ int get length => _raw.length;
+ bool get isEmpty => _raw.isEmpty;
+ get first => _reader.inflateReference(_raw.first);
+ get last => _reader.inflateReference(_raw.last);
+
+ // These operations, and other inherited methods that iterate over the whole
+ // list will work, but may be expensive, and are probably
+ // best avoided.
+ List get _inflated => _raw.mappedBy(_reader.inflateReference);
+ Iterator get iterator => _inflated.iterator;
+ indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
+ lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
+
+ // These operations are all invalid
+ _throw() {
+ throw new UnsupportedError("Not modifiable");
+ }
+ operator []=(x, y) => _throw();
+ add(x) => _throw();
+ addLast(x) => _throw();
+ addAll(x) => _throw();
+ sort([f]) => _throw();
+ clear() => _throw();
+ removeAt(x) => _throw();
+ removeLast() => _throw();
+ getRange(x, y) => _throw();
+ setRange(x, y, z, [a]) => _throw();
+ removeRange(x, y) => _throw();
+ insertRange(x, y, [z]) => _throw();
+ void set length(x) => _throw();
+}
« no previous file with comments | « pkg/serialization/lib/src/serialization_helpers.dart ('k') | pkg/serialization/test/serialization_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698