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

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

Issue 1192103002: Support serialization of the compiler backbone. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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/compiler/lib/src/serialization/serialization.dart
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
new file mode 100644
index 0000000000000000000000000000000000000000..5dd1ce8fc81a51061ffc5fcf34f27887fc7d5420
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -0,0 +1,730 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.serialization;
+
+import '../elements/elements.dart';
+import '../constants/expressions.dart';
+import '../dart_types.dart';
+
+import 'element_serialization.dart';
+import 'constant_serialization.dart';
+import 'type_serialization.dart';
+import 'keys.dart';
+import 'json_serializer.dart';
+import 'values.dart';
+
+/// Abstract base interface for [ObjectSerializer] and [MapSerializer].
floitsch 2015/06/26 20:54:05 Misses documentation.
Johnni Winther 2015/07/03 12:13:45 Done.
+abstract class AbstractSerializer<K> {
+ /// Maps the [key] entry to the enum [value] in this serializer.
+ void setEnum(K key, var value);
+
+ /// Maps the [key] entry to the [element] in this serializer.
+ void setElement(K key, Element element);
+
+ /// Maps the [key] entry to the [elements] in this serializer.
+ ///
+ /// If [elements] is empty, it is skipped.
+ void setElements(K key, Iterable<Element> elements);
+
+ /// Maps the [key] entry to the [constant] in this serializer.
+ void setConstant(K key, ConstantExpression constant);
+
+ /// Maps the [key] entry to the [constants] in this serializer.
+ ///
+ /// If [constants] is empty, it is skipped.
+ void setConstants(K key, Iterable<ConstantExpression> constants);
+
+ /// Maps the [key] entry to the [type] in this serializer.
+ void setType(K key, DartType type);
+
+ /// Maps the [key] entry to the [types] in this serializer.
+ ///
+ /// If [types] is empty, it is skipped.
+ void setTypes(K key, Iterable<DartType> types);
+
+ /// Maps the [key] entry to the [uri] in this serializer using [baseUri] to
+ /// relatives the encoding.
+ ///
+ /// For instance, a source file like `sdk/lib/core/string.dart` should be
+ /// serialized relative to the library root.
+ void setUri(K key, Uri baseUri, Uri uri);
+
+ /// Maps the [key] entry to the string [value] in this serializer.
+ void setString(K key, String value);
+
+ /// Maps the [key] entry to the string [values] in this serializer.
+ ///
+ /// If [values] is empty, it is skipped.
+ void setStrings(K key, Iterable<String> values);
+
+ /// Maps the [key] entry to the bool [value] in this serializer.
+ void setBool(K key, bool value);
+
+ /// Maps the [key] entry to the int [value] in this serializer.
+ void setInt(K key, int value);
+
+ /// Maps the [key] entry to the int [values] in this serializer.
+ ///
+ /// If [values] is empty, it is skipped.
+ void setInts(K key, Iterable<int> values);
+
+ /// Maps the [key] entry to the double [value] in this serializer.
+ void setDouble(K key, double value);
+
+ /// Creates and returns an [ObjectSerializer] that is mapped to the [key]
+ /// entry in this serializer.
+ ObjectSerializer createObject(K key);
+
+ /// Creates and returns a [MapSerializer] that is mapped to the [key] entry in
+ /// this serializer.
+ MapSerializer createMap(K key);
+
+ /// Creates and returns a [ListSerializer] that is mapped to the [key] entry
+ /// in this serializer.
+ ListSerializer createList(K key);
+}
+
+/// A serializer that associates values with [Key]s.
floitsch 2015/06/26 20:54:05 Documentation.
Johnni Winther 2015/07/03 12:13:45 Done.
+abstract class ObjectSerializer implements AbstractSerializer<Key> {
+
+}
+
+/// A serializer that associates values with [String]s.
+abstract class MapSerializer implements AbstractSerializer<String> {
+
+}
+
+/// A serializer that contains a list of [ObjectSerializer]s or
+/// [MapSerializer]s.
floitsch 2015/06/26 20:54:05 this doesn't help. Why would I have a list of Obje
Johnni Winther 2015/07/03 12:13:45 Done.
+abstract class ListSerializer {
+ /// Creates an [ObjectSerializer] and adds it to this serializer.
+ ObjectSerializer createObject();
+
+ /// Creates an [ObjectSerializer] and adds it to this serializer.
+ MapSerializer createMap();
+}
+
+/// Abstract base interface for [ObjectDeserializer] and [MapDeserializer].
+abstract class AbstractDeserializer<K> {
+ /// Returns `true` if [key] has an associated value in this deserializer.
+ bool containsKey(K key);
+
+ /// Returns the enum value from the [enumValues] associated with [key] in this
+ /// deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// [defaultValue] is returned, otherwise an exception is thrown.
+ getEnum(K key, Iterable enumValues, {bool isOptional: false, defaultValue});
+
+ /// Returns the [Element] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// `null` is returned, otherwise an exception is thrown.
+ Element getElement(K key, {bool isOptional: false});
+
+ /// Returns the list of [Element] values associated with [key] in this
+ /// deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// and empty [List] is returned, otherwise an exception is thrown.
+ List<Element> getElements(K key, {bool isOptional: false});
+
+ /// Returns the [ConstantExpression] value associated with [key] in this
+ /// deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// `null` is returned, otherwise an exception is thrown.
+ ConstantExpression getConstant(K key, {bool isOptional: false});
+
+ /// Returns the list of [ConstantExpression] values associated with [key] in
+ /// this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// and empty [List] is returned, otherwise an exception is thrown.
+ List<ConstantExpression> getConstants(K key, {bool isOptional: false});
+
+ /// Returns the [DartType] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// `null` is returned, otherwise an exception is thrown.
+ DartType getType(K key, {bool isOptional: false});
+
+ /// Returns the list of [DartType] values associated with [key] in this
+ /// deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// and empty [List] is returned, otherwise an exception is thrown.
+ List<DartType> getTypes(K key, {bool isOptional: false});
+
+ /// Returns the [Uri] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// [defaultValue] is returned, otherwise an exception is thrown.
+ Uri getUri(K key, {bool isOptional: false, Uri defaultValue});
+
+ /// Returns the [String] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// [defaultValue] is returned, otherwise an exception is thrown.
+ String getString(K key, {bool isOptional: false, String defaultValue});
+
+ /// Returns the list of [String] values associated with [key] in this
+ /// deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// and empty [List] is returned, otherwise an exception is thrown.
+ List<String> getStrings(K key, {bool isOptional: false});
+
+ /// Returns the [bool] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// [defaultValue] is returned, otherwise an exception is thrown.
+ bool getBool(K key, {bool isOptional: false, bool defaultValue});
+
+ /// Returns the [int] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// [defaultValue] is returned, otherwise an exception is thrown.
+ int getInt(K key, {bool isOptional: false, int defaultValue});
+
+ /// Returns the list of [int] values associated with [key] in this
+ /// deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// and empty [List] is returned, otherwise an exception is thrown.
+ List<int> getInts(K key, {bool isOptional: false});
+
+ /// Returns the [double] value associated with [key] in this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// [defaultValue] is returned, otherwise an exception is thrown.
+ double getDouble(K key, {bool isOptional: false, double defaultValue});
+
+ /// Returns an [ObjectDeserializer] for the map value associated with [key] in
+ /// this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// `null` is returned, otherwise an exception is thrown.
+ ObjectDeserializer getObject(K key, {bool isOptional: false});
+
+ /// Returns an [MapDeserializer] for the map value associated with [key] in
+ /// this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// `null` is returned, otherwise an exception is thrown.
+ MapDeserializer getMap(K key, {bool isOptional: false});
+
+ /// Returns an [ListDeserializer] for the list value associated with [key] in
+ /// this deserializer.
+ ///
+ /// If no value is associated with [key], then if [isOptional] is `true`,
+ /// `null` is returned, otherwise an exception is thrown.
+ ListDeserializer getList(K key, {bool isOptional: false});
+}
+
+/// A deserializer where values are associated with [Key]s.
+abstract class ObjectDeserializer implements AbstractDeserializer<Key> {
+
+}
+
+/// A deserializer where values are associated with [String]s.
+abstract class MapDeserializer implements AbstractDeserializer<String> {
+ /// Applies [f] to every key in the deserializer.
+ void forEachKey(f(String key));
+}
+
+/// A deserializer of a list of map values.
floitsch 2015/06/26 20:54:05 what "map" values?
Johnni Winther 2015/07/03 12:13:45 Done.
+abstract class ListDeserializer {
+ /// The number of values in this deserializer.
+ int get length;
+
+ /// Returns an [ObjectDeserializer] for the [index]th map value in
+ /// this deserializer.
+ ObjectDeserializer getObject(int index);
+
+ /// Returns an [MapDeserializer] for the [index]th map value in
+ /// this deserializer.
+ MapDeserializer getMap(int index);
+}
+
+/// A nominal object containing its serialized value.
+abstract class DataObject {
+ /// The id for the object.
+ get id;
+
+ /// The serialized value of the object.
+ ObjectValue get objectValue;
+}
+
+/// Serializer for the transitive closure of a collection of libraries.
+// TODO(johnniwinther): Support per-library serialization and dependencies
+// between serialized subcomponent.
+class Serializer {
+ final SerializationEncoder _encoder;
+
+ Map<Element, DataObject> _elementMap = <Element, DataObject>{};
+ Map<ConstantExpression, DataObject> _constantMap =
+ <ConstantExpression, DataObject>{};
+ Map<DartType, DataObject> _typeMap = <DartType, DataObject>{};
+ List _pendingList = [];
+
+ Serializer(this._encoder);
+
+ /// Add the transitive closure of [library] to this serializer.
+ void serialize(LibraryElement library) {
+ _getElementValue(library);
floitsch 2015/06/26 20:54:05 Add comment, why we don't care for the ElementValu
Johnni Winther 2015/07/03 12:13:45 Done.
+ _emptyWorklist();
+ }
+
+ void _emptyWorklist() {
+ while (_pendingList.isNotEmpty) {
+ _pendingList.removeLast()();
+ }
+ }
+
+ DataObject _createDataObject(IntValue id, EnumValue kind) {
+ return _encoder.createDataObject(id, kind);
+ }
+
+ ObjectSerializer _createObjectSerializer(Serializer serializer,
+ DataObject dataObject) {
+ return _encoder.createObjectSerializer(serializer, dataObject);
+ }
+
+ DataObject _getElementData(Element element) {
+ if (element == null) {
+ throw new ArgumentError('Serializer._getElementData(null)');
+ }
+ return _elementMap.putIfAbsent(element, () {
+ for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
+ SerializedElementKind kind = serializer.getSerializedKind(element);
+ if (kind != null) {
+ DataObject dataObject = _createDataObject(
+ new IntValue(_elementMap.length), new EnumValue(kind));
+ _pendingList.add(() {
+ serializer.serialize(
floitsch 2015/06/26 20:54:05 Ideally (especially if we decide not to use the en
Johnni Winther 2015/07/03 12:13:45 You would need to pass the [Serializer] around the
+ element, _createObjectSerializer(this, dataObject), kind);
+ });
+ return dataObject;
+ }
+ }
+ throw new UnsupportedError(
+ 'Unsupported element: $element (${element.kind})');
+ });
+ }
+
+ ElementValue _getElementValue(Element element) {
+ return new ElementValue(element, _getElementData(element).id);
+ }
+
+ void setElement(Map<dynamic, Value> map, key, Element element) {
+ map[key] = _getElementValue(element);
+ }
+
+ void setElements(Map<dynamic, Value> map, key, List<Element> elements) {
+ if (elements.isNotEmpty) {
+ map[key] = new ListValue(elements.map(_getElementValue).toList());
+ }
+ }
+
+ DataObject _getConstantData(ConstantExpression constant) {
+ return _constantMap.putIfAbsent(constant, () {
+ DataObject dataObject = _createDataObject(
+ new IntValue(_constantMap.length), new EnumValue(constant.kind));
+ _pendingList.add(() => _serializeConstant(constant, dataObject));
+ return dataObject;
+ });
+ }
+
+ void _serializeConstant(ConstantExpression constant, DataObject dataObject) {
+ const ConstantSerializer().apply(constant,
+ _createObjectSerializer(this, dataObject));
+ }
+
+ ConstantValue _getConstantValue(ConstantExpression constant) {
+ return new ConstantValue(constant, _getConstantData(constant).id);
+ }
+
+ void setConstant(Map<dynamic, Value> map, key, ConstantExpression constant) {
+ map[key] = _getConstantValue(constant);
+ }
+
+ void setConstants(Map<dynamic, Value> map,
floitsch 2015/06/26 20:54:05 There is no reason to be imperative here. Return t
Johnni Winther 2015/07/03 12:13:45 Done.
+ key,
+ List<ConstantExpression> constants) {
+ if (constants.isNotEmpty) {
+ map[key] = new ListValue(constants.map(_getConstantValue).toList());
+ }
+ }
+
+ DataObject _getTypeData(DartType type) {
+ return _typeMap.putIfAbsent(type, () {
+ DataObject dataObject = _createDataObject(
+ new IntValue(_typeMap.length), new EnumValue(type.kind));
+ _pendingList.add(() => _serializeType(type, dataObject));
+ return dataObject;
+ });
+ }
+
+ void _serializeType(DartType type, DataObject dataObject) {
+ const TypeSerializer().apply(type,
+ _createObjectSerializer(this, dataObject));
+ }
+
+ TypeValue _getTypeValue(DartType type) {
+ return new TypeValue(type, _getTypeData(type).id);
+ }
+
+ void setType(Map<dynamic, Value> map, key, DartType type) {
+ map[key] = _getTypeValue(type);
+ }
+
+ void setTypes(Map<dynamic, Value> map, key, List<DartType> types) {
+ if (types.isNotEmpty) {
+ map[key] = new ListValue(types.map(_getTypeValue).toList());
+ }
+ }
+
+ void setBool(Map<dynamic, Value> map, key, bool value) {
+ map[key] = new BoolValue(value);
+ }
+
+ void setInt(Map<dynamic, Value> map, key, int value) {
+ map[key] = new IntValue(value);
+ }
+
+ void setInts(Map<dynamic, Value> map, key, List<int> values) {
+ if (values.isNotEmpty) {
+ map[key] = new ListValue(
+ values.map((v) => new IntValue(v)).toList());
+ }
+ }
+
+ void setDouble(Map<dynamic, Value> map, key, double value) {
+ map[key] = new DoubleValue(value);
+ }
+
+ void setString(Map<dynamic, Value> map, key, String value) {
+ map[key] = new StringValue(value);
+ }
+
+ void setStrings(Map<dynamic, Value> map, key, List<String> values) {
+ if (values.isNotEmpty) {
+ map[key] = new ListValue(
+ values.map((v) => new StringValue(v)).toList());
+ }
+ }
+
+ void setEnum(Map<dynamic, Value> map, key, value) {
+ map[key] = new EnumValue(value);
+ }
+
+ void setUri(Map<dynamic, Value> map, key, Uri baseUri, Uri value) {
+ map[key] = new UriValue(baseUri, value);
+ }
+
+ ObjectValue get objectValue {
+ Map<Key, Value> map = <Key, Value>{};
+ map[Key.ELEMENTS] =
+ new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
+ if (_typeMap.isNotEmpty) {
+ map[Key.TYPES] =
+ new ListValue(_typeMap.values.map((l) => l.objectValue).toList());
+ }
+ if (_constantMap.isNotEmpty) {
+ map[Key.CONSTANTS] =
+ new ListValue(_constantMap.values.map((l) => l.objectValue).toList());
+ }
+ return new ObjectValue(map);
+ }
+
+ String toText() {
+ return _encoder.encode(objectValue);
+ }
+
+ String prettyPrint() {
+ PrettyPrintEncoder encoder = new PrettyPrintEncoder();
+ return encoder.toText(objectValue);
+ }
+}
+
+/// Deserializer for a closed collection of libraries.
+// TODO(johnniwinther): Support per-library deserialization and dependencies
+// between deserialized subcomponent.
+class Deserializer {
+ final SerializationDecoder _decoder;
+ final _mainData;
floitsch 2015/06/26 20:54:05 mainData is not a good name.
Johnni Winther 2015/07/03 12:13:45 'mainData' -> 'headerObject'.
+ Map<int, Element> _elementMap = {};
+ Map<int, DartType> _typeMap = {};
+ Map<int, ConstantExpression> _constantMap = {};
+
+ Deserializer.fromText(String text, SerializationDecoder decoder)
+ : this._mainData = decoder.decode(text),
+ this._decoder = decoder;
+
+ List _readMainData(Key key) {
+ return _decoder.readMainData(_mainData, key);
+ }
+
+ _readEntry(data, key) {
+ return _decoder.readEntry(data, key);
+ }
+
+ /// Returns the [LibraryElement] for [uri] if part of the deserializer.
+ LibraryElement lookupLibrary(Uri uri) {
+ for (var data in _readMainData(Key.ELEMENTS)) {
+ SerializedElementKind kind =
+ getEnum(data, Key.KIND, SerializedElementKind.values);
+ if (kind == SerializedElementKind.LIBRARY) {
+ Uri libraryUri = getUri(data, Key.CANONICAL_URI);
+ if (libraryUri == uri) {
+ return getElement(data, Key.ID);
+ }
+ }
+ }
+ return null;
+ }
+
+ Element getElement(data, key, {bool isOptional: false}) {
+ int id = _readEntry(data, key);
+ if (id == null) {
+ if (isOptional) {
+ return null;
+ }
+ throw new StateError("Element value '$key' not found in $data.");
+ }
+ return _getElementById(id);
+ }
+
+ Element _getElementById(int id) {
+ if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
+ return _elementMap.putIfAbsent(id, () {
+ return ElementDeserializer.deserialize(
+ new JsonObjectDeserializer(this, _readMainData(Key.ELEMENTS)[id]));
+ });
+ }
+
+ List<Element> getElements(data, key, {bool isOptional: false}) {
+ List list = _readEntry(data, key);
+ if (list == null) {
+ if (isOptional) {
+ return const [];
+ }
+ throw new StateError("Elements value '$key' not found in $data.");
+ }
+ return list.map(_getElementById).toList();
+ }
+
+ DartType getType(data, key, {bool isOptional: false}) {
+ int id = _readEntry(data, key);
+ if (id == null) {
+ if (isOptional) {
+ return null;
+ }
+ throw new StateError("Type value '$key' not found in $data.");
+ }
+ return _getTypeById(id);
+ }
+
+ DartType _getTypeById(int id) {
+ if (id == null) throw new ArgumentError('Deserializer.getType(null)');
+ return _typeMap.putIfAbsent(id, () {
+ return TypeDeserializer.deserialize(
+ new JsonObjectDeserializer(this, _readMainData(Key.TYPES)[id]));
+ });
+ }
+
+ List<DartType> getTypes(data, key, {bool isOptional: false}) {
+ List list = _readEntry(data, key);
+ if (list == null) {
+ if (isOptional) {
+ return const [];
+ }
+ throw new StateError("Types value '$key' not found in $data.");
+ }
+ return list.map(_getTypeById).toList();
+ }
+
+ ConstantExpression getConstant(data, key, {bool isOptional: false}) {
+ int id = _readEntry(data, key);
+ if (id == null) {
+ if (isOptional) {
+ return null;
+ }
+ throw new StateError("Constant value '$key' not found in $data.");
+ }
+ return _getConstantById(id);
+ }
+
+ ConstantExpression _getConstantById(int id) {
+ if (id == null) throw new ArgumentError('Deserializer.getConstant(null)');
+ return _constantMap.putIfAbsent(id, () {
+ return ConstantDeserializer.deserialize(
+ new JsonObjectDeserializer(this, _readMainData(Key.CONSTANTS)[id]));
+ });
+ }
+
+ List<ConstantExpression> getConstants(data, key, {bool isOptional: false}) {
+ List list = _readEntry(data, key);
+ if (list == null) {
+ if (isOptional) {
+ return const [];
+ }
+ throw new StateError("Constants value '$key' not found in $data.");
+ }
+ return list.map(_getConstantById).toList();
+ }
+
+ bool getBool(data, key, {bool isOptional: false, bool defaultValue}) {
+ bool value = _readEntry(data, key);
+ if (value == null) {
+ if (isOptional || defaultValue != null) {
+ return defaultValue;
+ }
+ throw new StateError("bool value '$key' not found in $data.");
+ }
+ return value;
+ }
+
+ int getInt(data, key, {bool isOptional: false, int defaultValue}) {
+ int value = _readEntry(data, key);
+ if (value == null) {
+ if (isOptional || defaultValue != null) {
+ return defaultValue;
+ }
+ throw new StateError("int value '$key' not found in $data.");
+ }
+ return value;
+ }
+
+ List<int> getInts(data, key, {bool isOptional: false}) {
+ List list = _readEntry(data, key);
+ if (list == null) {
+ if (isOptional) {
+ return const [];
+ }
+ throw new StateError("Ints value '$key' not found in $data.");
+ }
+ return list;
+ }
+
+ double getDouble(data, key, {bool isOptional: false, double defaultValue}) {
+ double value = _readEntry(data, key);
+ if (value == null) {
+ if (isOptional || defaultValue != null) {
+ return defaultValue;
+ }
+ throw new StateError("double value '$key' not found in $data.");
+ }
+ return value;
+ }
+
+ String getString(data, key, {bool isOptional: false, String defaultValue}) {
+ String value = _readEntry(data, key);
+ if (value == null) {
+ if (isOptional || defaultValue != null) {
+ return defaultValue;
+ }
+ throw new StateError("String value '$key' not found in $data.");
+ }
+ return value;
+ }
+
+ List<String> getStrings(data, key, {bool isOptional: false}) {
+ List list = _readEntry(data, key);
+ if (list == null) {
+ if (isOptional) {
+ return const [];
+ }
+ throw new StateError("Strings value '$key' not found in $data.");
+ }
+ return list;
+ }
+
+ getEnum(data, key, List values,
+ {bool isOptional: false, defaultValue}) {
+ int value = _readEntry(data, key);
+ if (value == null) {
+ if (isOptional || defaultValue != null) {
+ return defaultValue;
+ }
+ throw new StateError("enum value '$key' not found in $data.");
+ }
+ return values[value];
+ }
+
+ ObjectDeserializer getObject(data, key, {bool isOptional: false}) {
+ Map map = _readEntry(data, key);
+ if (map == null) {
+ if (isOptional) {
+ return null;
+ }
+ throw new StateError("Object value '$key' not found in $data.");
+ }
+ return new JsonObjectDeserializer(this, map);
+ }
+
+ MapDeserializer getMap(data, key, {bool isOptional: false}) {
+ Map map = _readEntry(data, key);
+ if (map == null) {
+ if (isOptional) {
+ return null;
+ }
+ throw new StateError("Map value '$key' not found in $data.");
+ }
+ return new JsonMapDeserializer(this, map);
+ }
+
+ ListDeserializer getList(data, key, {bool isOptional: false}) {
+ List list = _readEntry(data, key);
+ if (list == null) {
+ if (isOptional) {
+ return null;
+ }
+ throw new StateError("List value '$key' not found in $data.");
+ }
+ return new JsonListDeserializer(this, list);
+ }
+
+ Uri getUri(data, key, {bool isOptional: false, Uri defaultValue}) {
+ // TODO(johnniwinther): Support scheme specific encoding.
+ String value = _readEntry(data, key);
+ if (value == null) {
+ if (isOptional || defaultValue != null) {
+ return defaultValue;
+ }
+ throw new StateError("Uri value '$key' not found in $data.");
+ }
+ return Uri.parse(value);
+ }
+}
+
+/// Strategy used by [Serializer] to define the memory and output encoding.
+// TODO(johnniwinther): Split output encoding from memory object encoding.
floitsch 2015/06/26 20:54:05 Yes. But by removing the memory strategy. Just go
Johnni Winther 2015/07/03 12:13:45 Done.
+abstract class SerializationEncoder {
+ /// Encode [objectValue] into text.
+ String encode(ObjectValue objectValue);
+
+ /// Create a [DataObject] for an entity with the given [id] and [kind].
+ DataObject createDataObject(IntValue id, EnumValue kind);
+
+ /// Create an [ObjectSerializer] for [dataObject].
+ ObjectSerializer createObjectSerializer(
+ Serializer serializer, DataObject dataObject);
+}
+
+/// Strategy used by [Deserializer] for decoding and reading data from a
+/// serialized output.
+// TODO(johnniwinther): Split input encoding from memory object encoding.
+abstract class SerializationDecoder {
+ /// Decode [text] into an internal data model.
+ decode(String text);
+
+ /// Read the main data entry for [key] from [mainData].
+ List readMainData(mainData, Key key);
+
+ /// Read the entry [key] from the [data] object.
+ readEntry(data, key);
+}

Powered by Google App Engine
This is Rietveld 408576698