Chromium Code Reviews| 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); |
| +} |