| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of serialization; | 5 part of serialization; |
| 6 | 6 |
| 7 // TODO(alanknight): We should have an example and tests for subclassing | 7 // TODO(alanknight): We should have an example and tests for subclassing |
| 8 // serialization rule rather than using the hard-coded ClosureToMap rule. And | 8 // serialization rule rather than using the hard-coded ClosureToMap rule. And |
| 9 // possibly an abstract superclass that's designed to be subclassed that way. | 9 // possibly an abstract superclass that's designed to be subclassed that way. |
| 10 /** | 10 /** |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 */ | 131 */ |
| 132 int get dataLength => 0; | 132 int get dataLength => 0; |
| 133 } | 133 } |
| 134 | 134 |
| 135 /** | 135 /** |
| 136 * This rule handles things that implement List. It will recreate them as | 136 * This rule handles things that implement List. It will recreate them as |
| 137 * whatever the default implemenation of List is on the target platform. | 137 * whatever the default implemenation of List is on the target platform. |
| 138 */ | 138 */ |
| 139 class ListRule extends SerializationRule { | 139 class ListRule extends SerializationRule { |
| 140 | 140 |
| 141 appliesTo(object, Writer w) => object is List; | 141 bool appliesTo(object, Writer w) => object is List; |
| 142 | 142 |
| 143 bool get storesStateAsLists => true; | 143 bool get storesStateAsLists => true; |
| 144 | 144 |
| 145 List extractState(List list, f, Writer w) { | 145 List extractState(List list, f, Writer w) { |
| 146 var result = new List(); | 146 var result = new List(); |
| 147 for (var each in list) { | 147 for (var each in list) { |
| 148 result.add(each); | 148 result.add(each); |
| 149 f(each); | 149 f(each); |
| 150 } | 150 } |
| 151 return result; | 151 return result; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 } | 189 } |
| 190 | 190 |
| 191 /** | 191 /** |
| 192 * This rule handles things that implement Map. It will recreate them as | 192 * This rule handles things that implement Map. It will recreate them as |
| 193 * whatever the default implemenation of Map is on the target platform. If a | 193 * whatever the default implemenation of Map is on the target platform. If a |
| 194 * map has string keys it will attempt to retain it as a map for JSON formats, | 194 * map has string keys it will attempt to retain it as a map for JSON formats, |
| 195 * otherwise it will store it as a list of references to keys and values. | 195 * otherwise it will store it as a list of references to keys and values. |
| 196 */ | 196 */ |
| 197 class MapRule extends SerializationRule { | 197 class MapRule extends SerializationRule { |
| 198 | 198 |
| 199 appliesTo(object, Writer w) => object is Map; | 199 bool appliesTo(object, Writer w) => object is Map; |
| 200 | 200 |
| 201 bool get storesStateAsMaps => true; | 201 bool get storesStateAsMaps => true; |
| 202 | 202 |
| 203 extractState(Map map, f, Writer w) { | 203 extractState(Map map, f, Writer w) { |
| 204 // Note that we make a copy here because flattening may be destructive. | 204 // Note that we make a copy here because flattening may be destructive. |
| 205 var newMap = new Map.from(map); | 205 var newMap = new Map.from(map); |
| 206 newMap.forEach((key, value) { | 206 newMap.forEach((key, value) { |
| 207 f(key); | 207 f(key); |
| 208 f(value); | 208 f(value); |
| 209 }); | 209 }); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 | 265 |
| 266 bool get hasVariableLengthEntries => true; | 266 bool get hasVariableLengthEntries => true; |
| 267 } | 267 } |
| 268 | 268 |
| 269 /** | 269 /** |
| 270 * This rule handles primitive types, defined as those that we can normally | 270 * This rule handles primitive types, defined as those that we can normally |
| 271 * represent directly in the output format. We hard-code that to mean | 271 * represent directly in the output format. We hard-code that to mean |
| 272 * num, String, and bool. | 272 * num, String, and bool. |
| 273 */ | 273 */ |
| 274 class PrimitiveRule extends SerializationRule { | 274 class PrimitiveRule extends SerializationRule { |
| 275 appliesTo(object, Writer w) { | 275 bool appliesTo(object, Writer w) => isPrimitive(object); |
| 276 return isPrimitive(object); | |
| 277 } | |
| 278 extractState(object, Function f, Writer w) => object; | 276 extractState(object, Function f, Writer w) => object; |
| 279 flatten(object, Writer writer) {} | 277 flatten(object, Writer writer) {} |
| 280 inflateEssential(state, Reader r) => state; | 278 inflateEssential(state, Reader r) => state; |
| 281 inflateNonEssential(object, _, Reader r) {} | 279 inflateNonEssential(object, _, Reader r) {} |
| 282 | 280 |
| 283 bool get storesStateAsPrimitives => true; | 281 bool get storesStateAsPrimitives => true; |
| 284 | 282 |
| 285 /** | 283 /** |
| 286 * Indicate whether we should save pointers to this object as references | 284 * Indicate whether we should save pointers to this object as references |
| 287 * or store the object directly. For primitives this depends on the format, | 285 * or store the object directly. For primitives this depends on the format, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 327 */ | 325 */ |
| 328 ClosureRule(this.type, this.getStateFunction, this.construct, | 326 ClosureRule(this.type, this.getStateFunction, this.construct, |
| 329 this.setNonEssentialState); | 327 this.setNonEssentialState); |
| 330 | 328 |
| 331 bool appliesTo(object, Writer w) => object.runtimeType == type; | 329 bool appliesTo(object, Writer w) => object.runtimeType == type; |
| 332 | 330 |
| 333 getState(object) => getStateFunction(object); | 331 getState(object) => getStateFunction(object); |
| 334 | 332 |
| 335 create(state) => construct(state); | 333 create(state) => construct(state); |
| 336 | 334 |
| 337 setState(object, state) { | 335 void setState(object, state) { |
| 338 if (setNonEssentialState == null) return; | 336 if (setNonEssentialState == null) return; |
| 339 setNonEssentialState(object, state); | 337 setNonEssentialState(object, state); |
| 340 } | 338 } |
| 341 } | 339 } |
| 342 | 340 |
| 343 /** | 341 /** |
| 344 * This rule handles things we can't pass directly, but only by reference. | 342 * This rule handles things we can't pass directly, but only by reference. |
| 345 * If objects are listed in the namedObjects in the writer or serialization, | 343 * If objects are listed in the namedObjects in the writer or serialization, |
| 346 * it will save the name rather than saving the state. | 344 * it will save the name rather than saving the state. |
| 347 */ | 345 */ |
| (...skipping 24 matching lines...) Expand all Loading... |
| 372 } | 370 } |
| 373 | 371 |
| 374 /** Look up the named object and return it. */ | 372 /** Look up the named object and return it. */ |
| 375 inflateEssential(state, Reader r) => | 373 inflateEssential(state, Reader r) => |
| 376 r.objectNamed(r.resolveReference(state.first)); | 374 r.objectNamed(r.resolveReference(state.first)); |
| 377 | 375 |
| 378 /** Set any non-essential state on the object. For this rule, a no-op. */ | 376 /** Set any non-essential state on the object. For this rule, a no-op. */ |
| 379 inflateNonEssential(state, object, Reader r) {} | 377 inflateNonEssential(state, object, Reader r) {} |
| 380 | 378 |
| 381 /** Return the name for this object in the Writer. */ | 379 /** Return the name for this object in the Writer. */ |
| 382 nameFor(object, Writer writer) => writer.nameFor(object); | 380 String nameFor(object, Writer writer) => writer.nameFor(object); |
| 383 } | 381 } |
| 384 | 382 |
| 385 /** | 383 /** |
| 386 * This rule handles the special case of Mirrors. It stores the mirror by its | 384 * This rule handles the special case of Mirrors. It stores the mirror by its |
| 387 * qualifiedName and attempts to look it up in both the namedObjects | 385 * qualifiedName and attempts to look it up in both the namedObjects |
| 388 * collection, or if it's not found there, by looking it up in the mirror | 386 * collection, or if it's not found there, by looking it up in the mirror |
| 389 * system. When reading, the user is responsible for supplying the appropriate | 387 * system. When reading, the user is responsible for supplying the appropriate |
| 390 * values in [Serialization.namedObjects] or in the [externals] paramter to | 388 * values in [Serialization.namedObjects] or in the [externals] paramter to |
| 391 * [Serialization.read]. | 389 * [Serialization.read]. |
| 392 */ | 390 */ |
| 393 class MirrorRule extends NamedObjectRule { | 391 class MirrorRule extends NamedObjectRule { |
| 394 bool appliesTo(object, Writer writer) => object is DeclarationMirror; | 392 bool appliesTo(object, Writer writer) => object is DeclarationMirror; |
| 395 nameFor(DeclarationMirror object, Writer writer) => | 393 |
| 394 String nameFor(DeclarationMirror object, Writer writer) => |
| 396 MirrorSystem.getName(object.qualifiedName); | 395 MirrorSystem.getName(object.qualifiedName); |
| 397 | 396 |
| 398 inflateEssential(state, Reader r) { | 397 inflateEssential(state, Reader r) { |
| 399 var qualifiedName = r.resolveReference(state.first); | 398 var qualifiedName = r.resolveReference(state.first); |
| 400 var lookupFull = r.objectNamed(qualifiedName, (x) => null); | 399 var lookupFull = r.objectNamed(qualifiedName, (x) => null); |
| 401 if (lookupFull != null) return lookupFull; | 400 if (lookupFull != null) return lookupFull; |
| 402 var separatorIndex = qualifiedName.lastIndexOf("."); | 401 var separatorIndex = qualifiedName.lastIndexOf("."); |
| 403 var type = qualifiedName.substring(separatorIndex + 1); | 402 var type = qualifiedName.substring(separatorIndex + 1); |
| 404 var lookup = r.objectNamed(type, (x) => null); | 403 var lookup = r.objectNamed(type, (x) => null); |
| 405 if (lookup != null) return lookup; | 404 if (lookup != null) return lookup; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 | 472 |
| 474 inflateEssential(state, Reader r) => create(_lazy(state, r)); | 473 inflateEssential(state, Reader r) => create(_lazy(state, r)); |
| 475 | 474 |
| 476 void inflateNonEssential(state, object, Reader r) { | 475 void inflateNonEssential(state, object, Reader r) { |
| 477 setState(object, _lazy(state, r)); | 476 setState(object, _lazy(state, r)); |
| 478 } | 477 } |
| 479 | 478 |
| 480 // We don't want to have to make the end user tell us how long the list is | 479 // We don't want to have to make the end user tell us how long the list is |
| 481 // separately, so write it out for each object, even though they're all | 480 // separately, so write it out for each object, even though they're all |
| 482 // expected to be the same length. | 481 // expected to be the same length. |
| 483 get hasVariableLengthEntries => true; | 482 bool get hasVariableLengthEntries => true; |
| 484 } | 483 } |
| 485 | 484 |
| 486 /** A hard-coded rule for serializing Symbols. */ | 485 /** A hard-coded rule for serializing Symbols. */ |
| 487 class SymbolRule extends CustomRule { | 486 class SymbolRule extends CustomRule { |
| 488 bool appliesTo(instance, _) => instance is Symbol; | 487 bool appliesTo(instance, _) => instance is Symbol; |
| 489 getState(instance) => [MirrorSystem.getName(instance)]; | 488 getState(instance) => [MirrorSystem.getName(instance)]; |
| 490 create(state) => new Symbol(state[0]); | 489 create(state) => new Symbol(state[0]); |
| 491 setState(symbol, state) {} | 490 void setState(symbol, state) {} |
| 492 int get dataLength => 1; | 491 int get dataLength => 1; |
| 493 bool get hasVariableLengthEntries => false; | 492 bool get hasVariableLengthEntries => false; |
| 494 } | 493 } |
| 495 | 494 |
| 496 /** Create a lazy list/map that will inflate its items on demand in [r]. */ | 495 /** Create a lazy list/map that will inflate its items on demand in [r]. */ |
| 497 _lazy(l, Reader r) { | 496 _lazy(l, Reader r) { |
| 498 if (l is List) return new _LazyList(l, r); | 497 if (l is List) return new _LazyList(l, r); |
| 499 if (l is Map) return new _LazyMap(l, r); | 498 if (l is Map) return new _LazyMap(l, r); |
| 500 throw new SerializationException("Invalid type: must be Map or List - $l"); | 499 throw new SerializationException("Invalid type: must be Map or List - $l"); |
| 501 } | 500 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 removeWhere(x) => _throw(); | 589 removeWhere(x) => _throw(); |
| 591 retainWhere(x) => _throw(); | 590 retainWhere(x) => _throw(); |
| 592 replaceRange(x, y, z) => _throw(); | 591 replaceRange(x, y, z) => _throw(); |
| 593 getRange(x, y) => _throw(); | 592 getRange(x, y) => _throw(); |
| 594 setRange(x, y, z, [a = 0]) => _throw(); | 593 setRange(x, y, z, [a = 0]) => _throw(); |
| 595 setAll(x, y) => _throw(); | 594 setAll(x, y) => _throw(); |
| 596 removeRange(x, y) => _throw(); | 595 removeRange(x, y) => _throw(); |
| 597 get reversed => _throw(); | 596 get reversed => _throw(); |
| 598 void set length(x) => _throw(); | 597 void set length(x) => _throw(); |
| 599 } | 598 } |
| OLD | NEW |