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 5c397b06d7707e95aed20ee8574f09d358965ed1..8c58af638e310cbad099689ac8421af475a840f0 100644 |
--- a/pkg/serialization/lib/src/serialization_rule.dart |
+++ b/pkg/serialization/lib/src/serialization_rule.dart |
@@ -45,7 +45,7 @@ abstract class SerializationRule { |
* state at the end. The state that results will still have direct |
* pointers to objects, rather than references. |
*/ |
- extractState(object, void f(value)); |
+ extractState(object, void f(value), Writer w); |
/** |
* Allows rules to tell us how they expect to store their state. If this |
@@ -142,7 +142,7 @@ class ListRule extends SerializationRule { |
bool get storesStateAsLists => true; |
- List extractState(List list, f) { |
+ List extractState(List list, f, Writer w) { |
var result = new List(); |
for (var each in list) { |
result.add(each); |
@@ -200,7 +200,7 @@ class MapRule extends SerializationRule { |
bool get storesStateAsMaps => true; |
- extractState(Map map, f) { |
+ extractState(Map map, f, Writer w) { |
// Note that we make a copy here because flattening may be destructive. |
var newMap = new Map.from(map); |
newMap.forEach((key, value) { |
@@ -219,7 +219,7 @@ class MapRule extends SerializationRule { |
*/ |
flatten(Map state, Writer writer) { |
bool keysAreAllStrings = state.keys.every((x) => x is String); |
- if (keysAreAllStrings) { |
+ if (keysAreAllStrings && !writer.shouldUseReferencesForPrimitives) { |
keysAndValues(state).forEach( |
(key, value) => state[key] = writer._referenceFor(value)); |
return state; |
@@ -275,7 +275,7 @@ class PrimitiveRule extends SerializationRule { |
appliesTo(object, Writer w) { |
return isPrimitive(object); |
} |
- extractState(object, Function f) => object; |
+ extractState(object, Function f, Writer w) => object; |
flatten(object, Writer writer) {} |
inflateEssential(state, Reader r) => state; |
inflateNonEssential(object, _, Reader r) {} |
@@ -355,7 +355,11 @@ class NamedObjectRule extends SerializationRule { |
} |
/** Extract the state of the named objects as just the object itself. */ |
- extractState(object, Function f) => [object]; |
+ extractState(object, Function f, Writer writer) { |
+ var result = [nameFor(object, writer)]; |
+ f(result.first); |
+ return result; |
+ } |
/** When we flatten the state we save it as the name. */ |
// TODO(alanknight): This seems questionable. In a truly flat format we may |
@@ -364,11 +368,12 @@ class NamedObjectRule extends SerializationRule { |
// extractState, and I'm reluctant to add yet another parameter until |
// proven necessary. |
flatten(state, Writer writer) { |
- state[0] = nameFor(state.first, writer); |
+ state[0] = writer._referenceFor(state[0]); |
} |
/** Look up the named object and return it. */ |
- inflateEssential(state, Reader r) => r.objectNamed(state.first); |
+ inflateEssential(state, Reader r) => |
+ r.objectNamed(r.resolveReference(state.first)); |
/** Set any non-essential state on the object. For this rule, a no-op. */ |
inflateNonEssential(state, object, Reader r) {} |
@@ -378,15 +383,28 @@ class NamedObjectRule extends SerializationRule { |
} |
/** |
- * This rule handles the special case of Mirrors, restricted to those that |
- * have a simpleName. It knows that it applies to any such mirror and |
- * automatically uses its simpleName as the key into the namedObjects. |
- * When reading, the user is still responsible for adding the appropriate |
- * mirrors to namedObject. |
+ * This rule handles the special case of Mirrors. It stores the mirror by its |
+ * qualifiedName and attempts to look it up in both the namedObjects |
+ * collection, or if it's not found there, by looking it up in the mirror |
+ * system. When reading, the user is responsible for supplying the appropriate |
+ * values in [namedObjects] or in the [externals] paramter to |
+ * [Serialization.read]. |
*/ |
class MirrorRule extends NamedObjectRule { |
bool appliesTo(object, Writer writer) => object is DeclarationMirror; |
- nameFor(DeclarationMirror object, Writer writer) => object.simpleName; |
+ nameFor(DeclarationMirror object, Writer writer) => object.qualifiedName; |
+ |
+ inflateEssential(state, Reader r) { |
+ var qualifiedName = r.resolveReference(state.first); |
+ var lookupFull = r.objectNamed(qualifiedName, (x) => null); |
+ if (lookupFull != null) return lookupFull; |
+ var lib = qualifiedName.substring(0, qualifiedName.indexOf(".")); |
+ var type = qualifiedName.substring(qualifiedName.indexOf(".") + 1); |
+ var lookup = r.objectNamed(type, (x) => null); |
+ if (lookup != null) return lookup; |
+ var libMirror = currentMirrorSystem().libraries[lib]; |
+ return libMirror.classes[type]; |
+ } |
} |
/** |
@@ -430,7 +448,7 @@ abstract class CustomRule extends SerializationRule { |
*/ |
void setState(object, List state); |
- extractState(instance, Function f) { |
+ extractState(instance, Function f, Writer w) { |
var state = getState(instance); |
for (var each in values(state)) { |
f(each); |
@@ -440,8 +458,9 @@ abstract class CustomRule extends SerializationRule { |
inflateEssential(state, Reader r) => create(_lazy(state, r)); |
- void inflateNonEssential(state, object, Reader r) => |
- setState(object, _lazy(state, r)); |
+ void inflateNonEssential(state, object, Reader r) { |
+ setState(object, _lazy(state, r)); |
+ } |
// 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 |