Chromium Code Reviews| Index: pkg/compiler/lib/src/serialization/json_serializer.dart |
| diff --git a/pkg/compiler/lib/src/serialization/json_serializer.dart b/pkg/compiler/lib/src/serialization/json_serializer.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f27dc4aea8eed0d586586a6bf0e3c8c923a7c6d6 |
| --- /dev/null |
| +++ b/pkg/compiler/lib/src/serialization/json_serializer.dart |
| @@ -0,0 +1,523 @@ |
| +// 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.json; |
| + |
| +import 'dart:convert'; |
| +import '../constants/expressions.dart'; |
| +import '../dart_types.dart'; |
| +import '../elements/elements.dart'; |
| +import 'keys.dart'; |
| +import 'serialization.dart'; |
| +import 'values.dart'; |
| + |
| +/// Serialization encoder for JSON. |
| +class JsonSerializationEncoder implements SerializationEncoder { |
| + const JsonSerializationEncoder(); |
| + |
| + String encode(ObjectValue objectValue) { |
| + return new JsonEncoder.withIndent(' ').convert( |
| + const JsonObjectEncoder().apply(objectValue)); |
| + } |
| + |
| + JsonDataObject createDataObject(IntValue id, EnumValue kind) { |
| + return new JsonDataObject(id, kind); |
| + } |
| + |
| + ObjectSerializer createObjectSerializer(Serializer serializer, |
| + JsonDataObject dataObject) { |
| + return new MapBasedObjectSerializer(serializer, dataObject.map); |
| + } |
| +} |
| + |
| +/// Serialiation decoder for JSON. |
|
floitsch
2015/06/26 20:54:04
Serialization
Johnni Winther
2015/07/03 12:13:45
Done.
|
| +class JsonSerializationDecoder implements SerializationDecoder { |
| + const JsonSerializationDecoder(); |
| + |
| + decode(String text) => JSON.decode(text); |
| + |
| + List readMainData(Map mainData, Key key) => mainData[key.name]; |
| + |
| + readEntry(Map data, key) => data[key.toString()]; |
| +} |
| + |
| +/// A map based [DataObject]. |
| +class JsonDataObject implements DataObject { |
| + final Value id; |
| + final ObjectValue objectValue; |
| + |
| + JsonDataObject(Value id, EnumValue kind) |
| + : this.id = id, |
| + this.objectValue = |
| + new ObjectValue(<Key, Value>{Key.ID: id, Key.KIND: kind}); |
| + |
| + Map<Key, Value> get map => objectValue.map; |
| +} |
| + |
| +/// An [AbstractSerializer] that stores the values in a [Map]. |
| +abstract class AbstractMapBasedSerializer<K> implements AbstractSerializer<K> { |
| + final Serializer _serializer; |
| + final Map<K, Value> _map; |
| + |
| + AbstractMapBasedSerializer(this._serializer, this._map); |
| + |
| + @override |
| + ListSerializer createList(K key) { |
| + List<Value> list = <Value>[]; |
| + _map[key] = new ListValue(list); |
| + return new ListBasedListSerializer(_serializer, list); |
| + } |
| + |
| + @override |
| + MapSerializer createMap(K key) { |
| + Map<String, Value> map = <String, Value>{}; |
| + _map[key] = new MapValue(map); |
| + return new MapBasedMapSerializer(_serializer, map); |
| + } |
| + |
| + @override |
| + ObjectSerializer createObject(K key) { |
| + Map<Key, Value> map = <Key, Value>{}; |
| + _map[key] = new ObjectValue(map); |
| + return new MapBasedObjectSerializer(_serializer, map); |
| + } |
| + |
| + @override |
| + void setBool(K key, bool value) { |
| + _serializer.setBool(_map, key, value); |
| + } |
| + |
| + @override |
| + void setConstant(K key, ConstantExpression constant) { |
| + _serializer.setConstant(_map, key, constant); |
| + } |
| + |
| + @override |
| + void setConstants(K key, Iterable<ConstantExpression> constants) { |
| + _serializer.setConstants(_map, key, constants); |
| + } |
| + |
| + @override |
| + void setDouble(K key, double value) { |
| + _serializer.setDouble(_map, key, value); |
| + } |
| + |
| + @override |
| + void setElement(K key, Element element) { |
| + _serializer.setElement(_map, key, element); |
| + } |
| + |
| + @override |
| + void setElements(K key, Iterable<Element> elements) { |
| + _serializer.setElements(_map, key, elements); |
| + } |
| + |
| + @override |
| + void setEnum(K key, value) { |
| + _serializer.setEnum(_map, key, value); |
| + } |
| + |
| + @override |
| + void setInt(K key, int value) { |
| + _serializer.setInt(_map, key, value); |
| + } |
| + |
| + @override |
| + void setInts(K key, List<int> values) { |
| + _serializer.setInts(_map, key, values); |
| + } |
| + |
| + @override |
| + void setString(K key, String value) { |
| + _serializer.setString(_map, key, value); |
| + } |
| + |
| + @override |
| + void setStrings(K key, Iterable<String> values) { |
| + _serializer.setStrings(_map, key, values); |
| + } |
| + |
| + @override |
| + void setType(K key, DartType type) { |
| + _serializer.setType(_map, key, type); |
| + } |
| + |
| + @override |
| + void setTypes(K key, List<DartType> types) { |
| + _serializer.setTypes(_map, key, types); |
| + } |
| + |
| + @override |
| + void setUri(K key, Uri baseUri, Uri uri) { |
| + _serializer.setUri(_map, key, baseUri, uri); |
| + } |
| + |
| + String toString() => _map.toString(); |
| +} |
| + |
| +/// An [ObjectSerializer] that stores the values in a [Map]. |
| +class MapBasedObjectSerializer extends AbstractMapBasedSerializer |
| + implements ObjectSerializer { |
| + MapBasedObjectSerializer(Serializer serializer, Map<dynamic, Value> map) |
| + : super(serializer, map); |
| +} |
| + |
| +/// An [MapSerializer] that stores the values in a [Map]. |
| +class MapBasedMapSerializer extends AbstractMapBasedSerializer<String> |
| + implements MapSerializer { |
| + MapBasedMapSerializer(Serializer serializer, Map<String, Value> map) |
| + : super(serializer, map); |
| +} |
| + |
| +/// An [ListSerializer] that stores the values in a [List]. |
| +class ListBasedListSerializer implements ListSerializer { |
| + final Serializer _serializer; |
| + final List<Value> _list; |
| + |
| + ListBasedListSerializer(this._serializer, this._list); |
| + |
| + @override |
| + MapSerializer createMap() { |
| + Map<String, Value> map = {}; |
| + _list.add(new MapValue(map)); |
| + return new MapBasedMapSerializer(_serializer, map); |
| + } |
| + |
| + @override |
| + ObjectSerializer createObject() { |
| + Map<Key, Value> map = <Key, Value>{}; |
| + _list.add(new ObjectValue(map)); |
| + return new MapBasedObjectSerializer(_serializer, map); |
| + } |
| +} |
| + |
| +/// Base implementation of [AbstractDeserializer] based on a JSON encoded [Map]. |
| +abstract class AbstractJsonDeserializer<K> implements AbstractDeserializer<K> { |
| + final Deserializer _deserializer; |
| + final Map<K, dynamic> _map; |
| + |
| + AbstractJsonDeserializer(this._deserializer, this._map) { |
| + assert(_deserializer != null); |
| + assert(_map != null); |
| + } |
| + |
| + @override |
| + bool getBool(K key, {bool isOptional: false, bool defaultValue}) { |
| + return _deserializer.getBool( |
| + _map, key, isOptional: isOptional, defaultValue: defaultValue); |
| + } |
| + |
| + @override |
| + ConstantExpression getConstant(K key, {bool isOptional: false}) { |
| + return _deserializer.getConstant(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + List<ConstantExpression> getConstants(K key, {bool isOptional: false}) { |
| + return _deserializer.getConstants(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + double getDouble(K key, {bool isOptional: false, double defaultValue}) { |
| + return _deserializer.getDouble( |
| + _map, key, isOptional: isOptional, defaultValue: defaultValue); |
| + } |
| + |
| + @override |
| + Element getElement(K key, {bool isOptional: false}) { |
| + return _deserializer.getElement(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + List<Element> getElements(K key, {bool isOptional: false}) { |
| + return _deserializer.getElements(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + getEnum(K key, Iterable enumValues, {bool isOptional: false, defaultValue}) { |
| + return _deserializer.getEnum( |
| + _map, key, enumValues, |
| + isOptional: isOptional, defaultValue: defaultValue); |
| + } |
| + |
| + @override |
| + int getInt(K key, {bool isOptional: false, int defaultValue}) { |
| + return _deserializer.getInt( |
| + _map, key, isOptional: isOptional, defaultValue: defaultValue); |
| + } |
| + |
| + @override |
| + List<int> getInts(K key, {bool isOptional: false}) { |
| + return _deserializer.getInts( |
| + _map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + ListDeserializer getList(K key, {bool isOptional: false}) { |
| + return _deserializer.getList(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + MapDeserializer getMap(K key, {bool isOptional: false}) { |
| + return _deserializer.getMap(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + ObjectDeserializer getObject(K key, {bool isOptional: false}) { |
| + return _deserializer.getObject(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + String getString(K key, {bool isOptional: false, String defaultValue}) { |
| + return _deserializer.getString( |
| + _map, key, isOptional: isOptional, defaultValue: defaultValue); |
| + } |
| + |
| + @override |
| + List<String> getStrings(K key, {bool isOptional: false}) { |
| + return _deserializer.getStrings(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + DartType getType(K key, {bool isOptional: false}) { |
| + return _deserializer.getType(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + List<DartType> getTypes(K key, {bool isOptional: false}) { |
| + return _deserializer.getTypes(_map, key, isOptional: isOptional); |
| + } |
| + |
| + @override |
| + Uri getUri(K key, {bool isOptional: false, Uri defaultValue}) { |
| + return _deserializer.getUri( |
| + _map, key, isOptional: isOptional, defaultValue: defaultValue); |
| + } |
| +} |
| + |
| +/// [ObjectDeserializer] based on a JSON-encoded [Map]. |
| +class JsonObjectDeserializer extends AbstractJsonDeserializer<Key> |
| + implements ObjectDeserializer { |
| + JsonObjectDeserializer(Deserializer deserializer, Map map) |
| + : super(deserializer, map); |
| + |
| + @override |
| + bool containsKey(Key key) => _map.containsKey(key.name); |
| +} |
| + |
| +/// [MapDeserializer] based on a JSON-encoded [Map]. |
| +class JsonMapDeserializer extends AbstractJsonDeserializer<String> |
| + implements MapDeserializer { |
| + JsonMapDeserializer(Deserializer deserializer, Map<String, dynamic> map) |
| + : super(deserializer, map); |
| + |
| + @override |
| + bool containsKey(String key) => _map.containsKey(key); |
| + |
| + @override |
| + void forEachKey(f(String key)) { |
| + _map.keys.forEach(f); |
| + } |
| +} |
| + |
| +/// [ListDeserializer] based on a JSON encoded [List]. |
| +class JsonListDeserializer implements ListDeserializer { |
| + final Deserializer _deserializer; |
| + final List _list; |
| + |
| + JsonListDeserializer(this._deserializer, this._list); |
| + |
| + @override |
| + MapDeserializer getMap(int index) { |
| + return new JsonMapDeserializer(_deserializer, _list[index]); |
| + } |
| + |
| + @override |
| + ObjectDeserializer getObject(int index) { |
| + return new JsonObjectDeserializer(_deserializer, _list[index]); |
| + } |
| + |
| + @override |
| + int get length => _list.length; |
| +} |
| + |
| +/// A [ValueVisitor] that computes a JSON object value. |
| +class JsonObjectEncoder implements ValueVisitor { |
| + const JsonObjectEncoder(); |
| + |
| + convert(Value value) => apply(value, this); |
| + |
| + @override |
| + apply(Value value, [arg]) => value.accept(this, arg); |
| + |
| + @override |
| + bool visitBool(BoolValue value, arg) => value.value; |
| + |
| + @override |
| + visitConstant(ConstantValue value, arg) => apply(value.id); |
| + |
| + @override |
| + double visitDouble(DoubleValue value, arg) => value.value; |
| + |
| + @override |
| + visitElement(ElementValue value, arg) => apply(value.id); |
| + |
| + @override |
| + visitEnum(EnumValue value, arg) => value.value.index; |
| + |
| + @override |
| + int visitInt(IntValue value, arg) => value.value; |
| + |
| + @override |
| + List visitList(ListValue value, arg) => value.values.map(apply).toList(); |
| + |
| + @override |
| + Map visitMap(MapValue value, arg) { |
| + Map<String, dynamic> map = <String, dynamic>{}; |
| + value.map.forEach((String key, Value value) { |
| + map[key] = apply(value); |
| + }); |
| + return map; |
| + } |
| + |
| + @override |
| + Map visitObject(ObjectValue value, arg) { |
| + Map<String, dynamic> map = <String, dynamic>{}; |
| + value.map.forEach((Key key, Value value) { |
| + map[key.name] = apply(value); |
| + }); |
| + return map; |
| + } |
| + |
| + @override |
| + String visitString(StringValue value, arg) => value.value; |
| + |
| + @override |
| + visitType(TypeValue value, arg) => apply(value.id); |
| + |
| + @override |
| + visitUri(UriValue value, arg) => '${value.value}'; |
| +} |
| + |
| +/// [ValueVisitor] that generates a verbose JSON-like output. |
| +class PrettyPrintEncoder implements ValueVisitor { |
| + StringBuffer buffer; |
| + |
| + String toText(Value value) { |
| + buffer = new StringBuffer(); |
| + apply(value, ''); |
| + String text = buffer.toString(); |
| + buffer = null; |
| + return text; |
| + } |
| + |
| + @override |
| + void apply(Value value, String indentation) { |
| + value.accept(this, indentation); |
| + } |
| + |
| + @override |
| + void visitBool(BoolValue value, String indentation) { |
| + buffer.write(value.value); |
| + } |
| + |
| + @override |
| + void visitConstant(ConstantValue value, String indentation) { |
| + buffer.write('Constant(${value.id}):${value.constant.getText()}'); |
| + } |
| + |
| + @override |
| + void visitDouble(DoubleValue value, String indentation) { |
| + buffer.write(value.value); |
| + } |
| + @override |
| + void visitElement(ElementValue value, String indentation) { |
| + buffer.write('Element(${value.id}):${value.element}'); |
| + } |
| + |
| + @override |
| + void visitEnum(EnumValue value, String indentation) { |
| + buffer.write(value.value); |
| + } |
| + |
| + @override |
| + void visitInt(IntValue value, String indentation) { |
| + buffer.write(value.value); |
| + } |
| + |
| + @override |
| + void visitList(ListValue value, String indentation) { |
| + if (value.values.isEmpty) { |
| + buffer.write('[]'); |
| + } else { |
| + buffer.write('['); |
| + bool needsComma = false; |
| + String nextIndentation = '${indentation} '; |
| + for (Value element in value.values) { |
| + if (needsComma) { |
| + buffer.write(','); |
| + } |
| + buffer.write('\n$nextIndentation'); |
| + apply(element, nextIndentation); |
| + needsComma = true; |
| + } |
| + buffer.write('\n$indentation]'); |
| + } |
| + } |
| + |
| + @override |
| + void visitMap(MapValue value, String indentation) { |
| + if (value.map.isEmpty) { |
| + buffer.write('{}'); |
| + } else { |
| + buffer.write('{'); |
| + bool needsComma = false; |
| + String nextIndentation = '${indentation} '; |
| + value.map.forEach((String key, Value subvalue) { |
| + if (needsComma) { |
| + buffer.write(','); |
| + } |
| + buffer.write('\n$nextIndentation$key: '); |
| + apply(subvalue, nextIndentation); |
| + needsComma = true; |
| + }); |
| + buffer.write('\n$indentation}'); |
| + } |
| + } |
| + |
| + @override |
| + void visitObject(ObjectValue value, String indentation) { |
| + if (value.map.isEmpty) { |
| + buffer.write('{}'); |
| + } else { |
| + buffer.write('{'); |
| + bool needsComma = false; |
| + String nextIndentation = '${indentation} '; |
| + value.map.forEach((Key key, Value subvalue) { |
| + if (needsComma) { |
| + buffer.write(','); |
| + } |
| + buffer.write('\n$nextIndentation$key: '); |
| + apply(subvalue, nextIndentation); |
| + needsComma = true; |
| + }); |
| + buffer.write('\n$indentation}'); |
| + } |
| + } |
| + |
| + @override |
| + void visitString(StringValue value, String indentation) { |
| + buffer.write('"${value.value}"'); |
| + } |
| + |
| + @override |
| + void visitType(TypeValue value, String indentation) { |
| + buffer.write('Type(${value.id}):${value.type}'); |
| + } |
| + |
| + @override |
| + void visitUri(UriValue value, String indentation) { |
| + buffer.write('Uri(${value.value})'); |
| + } |
| +} |