blob: 425f6d2621a2627e1683cd43b420fefc76e5664f [file] [log] [blame]
// Copyright (c) 2018, 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.
import 'dart:convert';
import 'dart:typed_data';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/binary/ast_from_binary.dart' as ir;
import 'package:kernel/binary/ast_to_binary.dart' as ir;
import '../closure.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../deferred_load.dart';
import '../diagnostics/source_span.dart';
import '../elements/entities.dart';
import '../elements/indexed.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../ir/constants.dart';
import '../ir/static_type_base.dart';
import '../js/js.dart' as js;
import '../js_model/closure.dart';
import '../js_model/locals.dart';
part 'abstract_sink.dart';
part 'abstract_source.dart';
part 'binary_sink.dart';
part 'binary_source.dart';
part 'helpers.dart';
part 'member_data.dart';
part 'mixins.dart';
part 'node_indexer.dart';
part 'object_sink.dart';
part 'object_source.dart';
/// Interface for serialization.
abstract class DataSink {
/// The amount of data written to this data sink.
///
/// The units is based on the underlying data structure for this data sink.
int get length;
/// Flushes any pending data and closes this data sink.
///
/// The data sink can no longer be written to after closing.
void close();
/// Registers that the section [tag] starts.
///
/// This is used for debugging to verify that sections are correctly aligned
/// between serialization and deserialization.
void begin(String tag);
/// Registers that the section [tag] ends.
///
/// This is used for debugging to verify that sections are correctly aligned
/// between serialization and deserialization.
void end(String tag);
/// Writes a reference to [value] to this data sink. If [value] has not yet
/// been serialized, [f] is called to serialize the value itself.
void writeCached<E>(E value, void f(E value));
/// Writes the potentially `null` [value] to this data sink. If [value] is
/// non-null [f] is called to write the non-null value to the data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readValueOrNull].
void writeValueOrNull<E>(E value, void f(E value));
/// Writes the [values] to this data sink calling [f] to write each value to
/// the data sink. If [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readList].
void writeList<E>(Iterable<E> values, void f(E value),
{bool allowNull: false});
/// Writes the boolean [value] to this data sink.
void writeBool(bool value);
/// Writes the non-negative 30 bit integer [value] to this data sink.
void writeInt(int value);
/// Writes the potentially `null` non-negative [value] to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readIntOrNull].
void writeIntOrNull(int value);
/// Writes the string [value] to this data sink.
void writeString(String value);
/// Writes the potentially `null` string [value] to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readStringOrNull].
void writeStringOrNull(String value);
/// Writes the string [values] to this data sink. If [allowNull] is `true`,
/// [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readStrings].
void writeStrings(Iterable<String> values, {bool allowNull: false});
/// Writes the [map] from string to [V] values to this data sink, calling [f]
/// to write each value to the data sink. If [allowNull] is `true`, [map] is
/// allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readStringMap].
void writeStringMap<V>(Map<String, V> map, void f(V value),
{bool allowNull: false});
/// Writes the enum value [value] to this data sink.
// TODO(johnniwinther): Change the signature to
// `void writeEnum<E extends Enum<E>>(E value);` when an interface for enums
// is added to the language.
void writeEnum(dynamic value);
/// Writes the URI [value] to this data sink.
void writeUri(Uri value);
/// Writes a reference to the kernel library node [value] to this data sink.
void writeLibraryNode(ir.Library value);
/// Writes a reference to the kernel class node [value] to this data sink.
void writeClassNode(ir.Class value);
/// Writes a reference to the kernel typedef node [value] to this data sink.
void writeTypedefNode(ir.Typedef value);
/// Writes a reference to the kernel member node [value] to this data sink.
void writeMemberNode(ir.Member value);
/// Writes references to the kernel member node [values] to this data sink.
/// If [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readMemberNodes].
void writeMemberNodes(Iterable<ir.Member> values, {bool allowNull: false});
/// Writes the [map] from references to kernel member nodes to [V] values to
/// this data sink, calling [f] to write each value to the data sink. If
/// [allowNull] is `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readMemberNodeMap].
void writeMemberNodeMap<V>(Map<ir.Member, V> map, void f(V value),
{bool allowNull: false});
/// Writes a kernel name node to this data sink.
void writeName(ir.Name value);
/// Writes a kernel library dependency node [value] to this data sink.
void writeLibraryDependencyNode(ir.LibraryDependency value);
/// Writes a potentially `null` kernel library dependency node [value] to
/// this data sink.
void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value);
/// Writes a reference to the kernel tree node [value] to this data sink.
void writeTreeNode(ir.TreeNode value);
/// Writes a reference to the potentially `null` kernel tree node [value]
/// to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readTreeNodeOrNull].
void writeTreeNodeOrNull(ir.TreeNode value);
/// Writes references to the kernel tree node [values] to this data sink.
/// If [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readTreeNodes].
void writeTreeNodes(Iterable<ir.TreeNode> values, {bool allowNull: false});
/// Writes the [map] from references to kernel tree nodes to [V] values to
/// this data sink, calling [f] to write each value to the data sink. If
/// [allowNull] is `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readTreeNodeMap].
void writeTreeNodeMap<V>(Map<ir.TreeNode, V> map, void f(V value),
{bool allowNull: false});
/// Writes a reference to the kernel tree node [value] in the known [context]
/// to this data sink.
void writeTreeNodeInContext(ir.TreeNode value);
/// Writes a reference to the potentially `null` kernel tree node [value] in
/// the known [context] to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readTreeNodeOrNullInContext].
void writeTreeNodeOrNullInContext(ir.TreeNode value);
/// Writes references to the kernel tree node [values] in the known [context]
/// to this data sink. If [allowNull] is `true`, [values] is allowed to be
/// `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readTreeNodesInContext].
void writeTreeNodesInContext(Iterable<ir.TreeNode> values,
{bool allowNull: false});
/// Writes the [map] from references to kernel tree nodes to [V] values in the
/// known [context] to this data sink, calling [f] to write each value to the
/// data sink. If [allowNull] is `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readTreeNodeMapInContext].
void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V> map, void f(V value),
{bool allowNull: false});
/// Writes a reference to the kernel type parameter node [value] to this data
/// sink.
void writeTypeParameterNode(ir.TypeParameter value);
/// Writes references to the kernel type parameter node [values] to this data
/// sink.
/// If [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readTypeParameterNodes].
void writeTypeParameterNodes(Iterable<ir.TypeParameter> values,
{bool allowNull: false});
/// Writes the type [value] to this data sink. If [allowNull] is `true`,
/// [value] is allowed to be `null`.
void writeDartType(DartType value, {bool allowNull: false});
/// Writes the type [values] to this data sink. If [allowNull] is `true`,
/// [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readDartTypes].
void writeDartTypes(Iterable<DartType> values, {bool allowNull: false});
/// Writes the kernel type node [value] to this data sink. If [allowNull] is
/// `true`, [value] is allowed to be `null`.
void writeDartTypeNode(ir.DartType value, {bool allowNull: false});
/// Writes the kernel type node [values] to this data sink. If [allowNull] is
/// `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readDartTypeNodes].
void writeDartTypeNodes(Iterable<ir.DartType> values,
{bool allowNull: false});
/// Writes the source span [value] to this data sink.
void writeSourceSpan(SourceSpan value);
/// Writes a reference to the indexed library [value] to this data sink.
void writeLibrary(IndexedLibrary value);
/// Writes a reference to the potentially `null` indexed library [value]
/// to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readLibraryOrNull].
void writeLibraryOrNull(IndexedLibrary value);
/// Writes the [map] from references to indexed libraries to [V] values to
/// this data sink, calling [f] to write each value to the data sink. If
/// [allowNull] is `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readLibraryMap].
void writeLibraryMap<V>(Map<LibraryEntity, V> map, void f(V value),
{bool allowNull: false});
/// Writes a reference to the indexed class [value] to this data sink.
void writeClass(IndexedClass value);
/// Writes a reference to the potentially `null` indexed class [value]
/// to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readClassOrNull].
void writeClassOrNull(IndexedClass value);
/// Writes references to the indexed class [values] to this data sink. If
/// [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readClasses].
void writeClasses(Iterable<ClassEntity> values, {bool allowNull: false});
/// Writes the [map] from references to indexed classes to [V] values to this
/// data sink, calling [f] to write each value to the data sink. If
/// [allowNull] is `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readClassMap].
void writeClassMap<V>(Map<ClassEntity, V> map, void f(V value),
{bool allowNull: false});
/// Writes a reference to the indexed typedef [value] to this data sink.
void writeTypedef(IndexedTypedef value);
/// Writes a reference to the indexed member [value] to this data sink.
void writeMember(IndexedMember value);
/// Writes a reference to the potentially `null` indexed member [value]
/// to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readMemberOrNull].
void writeMemberOrNull(IndexedMember value);
/// Writes references to the indexed member [values] to this data sink. If
/// [allowNull] is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readMembers].
void writeMembers(Iterable<MemberEntity> values, {bool allowNull: false});
/// Writes the [map] from references to indexed members to [V] values to this
/// data sink, calling [f] to write each value to the data sink. If
/// [allowNull] is `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readMemberMap].
void writeMemberMap<V>(
Map<MemberEntity, V> map, void f(MemberEntity member, V value),
{bool allowNull: false});
/// Writes a reference to the local [value] to this data sink.
void writeLocal(Local local);
/// Writes a reference to the potentially `null` local [value]
/// to this data sink.
///
/// This is a convenience method to be used together with
/// [DataSource.readLocalOrNull].
void writeLocalOrNull(Local local);
/// Writes references to the local [values] to this data sink. If [allowNull]
/// is `true`, [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readLocals].
void writeLocals(Iterable<Local> values, {bool allowNull: false});
/// Writes the [map] from references to locals to [V] values to this data
/// sink, calling [f] to write each value to the data sink. If [allowNull] is
/// `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readLocalMap].
void writeLocalMap<V>(Map<Local, V> map, void f(V value),
{bool allowNull: false});
/// Writes the constant [value] to this data sink.
void writeConstant(ConstantValue value);
/// Writes the potentially `null` constant [value] to this data sink.
void writeConstantOrNull(ConstantValue value);
/// Writes constant [values] to this data sink. If [allowNull] is `true`,
/// [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readConstants].
void writeConstants(Iterable<ConstantValue> values, {bool allowNull: false});
/// Writes the [map] from constant values to [V] values to this data sink,
/// calling [f] to write each value to the data sink. If [allowNull] is
/// `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readConstantMap].
void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value),
{bool allowNull: false});
/// Writes a double value to this data sink.
void writeDoubleValue(double value);
/// Writes an integer of arbitrary value to this data sink.
///
/// This is should only when the value is not known to be a non-negative
/// 30 bit integer. Otherwise [writeInt] should be used.
void writeIntegerValue(int value);
/// Writes the import [value] to this data sink.
void writeImport(ImportEntity value);
/// Writes the potentially `null` import [value] to this data sink.
void writeImportOrNull(ImportEntity value);
/// Writes import [values] to this data sink. If [allowNull] is `true`,
/// [values] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readImports].
void writeImports(Iterable<ImportEntity> values, {bool allowNull: false});
/// Writes the [map] from imports to [V] values to this data sink,
/// calling [f] to write each value to the data sink. If [allowNull] is
/// `true`, [map] is allowed to be `null`.
///
/// This is a convenience method to be used together with
/// [DataSource.readImportMap].
void writeImportMap<V>(Map<ImportEntity, V> map, void f(V value),
{bool allowNull: false});
/// Writes an abstract [value] to this data sink.
///
/// This feature is only available a [CodegenWriter] has been registered.
void writeAbstractValue(AbstractValue value);
/// Writes a reference to the output unit [value] to this data sink.
///
/// This feature is only available a [CodegenWriter] has been registered.
void writeOutputUnitReference(OutputUnit value);
/// Writes a js node [value] to this data sink.
///
/// This feature is only available a [CodegenWriter] has been registered.
void writeJsNode(js.Node value);
/// Writes a potentially `null` js node [value] to this data sink.
///
/// This feature is only available a [CodegenWriter] has been registered.
void writeJsNodeOrNull(js.Node value);
/// Register an [EntityWriter] with this data sink for non-default encoding
/// of entity references.
void registerEntityWriter(EntityWriter writer);
/// Register a [CodegenWriter] with this data sink to support serialization
/// of codegen only data.
void registerCodegenWriter(CodegenWriter writer);
/// Invoke [f] in the context of [member]. This sets up support for
/// serialization of `ir.TreeNode`s using the `writeTreeNode*InContext`
/// methods.
void inMemberContext(ir.Member member, void f());
}
/// Interface for deserialization.
abstract class DataSource {
/// Registers that the section [tag] starts.
///
/// This is used for debugging to verify that sections are correctly aligned
/// between serialization and deserialization.
void begin(String tag);
/// Registers that the section [tag] ends.
///
/// This is used for debugging to verify that sections are correctly aligned
/// between serialization and deserialization.
void end(String tag);
/// Registers a [ComponentLookup] object with this data source to support
/// deserialization of references to kernel nodes.
void registerComponentLookup(ComponentLookup componentLookup);
/// Registers an [EntityLookup] object with this data source to support
/// deserialization of references to indexed entities.
void registerEntityLookup(EntityLookup entityLookup);
/// Registers an [EntityReader] with this data source for non-default encoding
/// of entity references.
void registerEntityReader(EntityReader reader);
/// Registers a [LocalLookup] object with this data source to support
/// deserialization of references to locals.
void registerLocalLookup(LocalLookup localLookup);
/// Registers a [CodegenReader] with this data source to support
/// deserialization of codegen only data.
void registerCodegenReader(CodegenReader reader);
/// Unregisters the [CodegenReader] from this data source to remove support
/// for deserialization of codegen only data.
void deregisterCodegenReader(CodegenReader reader);
/// Invoke [f] in the context of [member]. This sets up support for
/// deserialization of `ir.TreeNode`s using the `readTreeNode*InContext`
/// methods.
T inMemberContext<T>(ir.Member member, T f());
/// Reads a reference to an [E] value from this data source. If the value has
/// not yet been deserialized, [f] is called to deserialize the value itself.
E readCached<E>(E f());
/// Reads a potentially `null` [E] value from this data source, calling [f] to
/// read the non-null value from the data source.
///
/// This is a convenience method to be used together with
/// [DataSink.writeValueOrNull].
E readValueOrNull<E>(E f());
/// Reads a list of [E] values from this data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeList].
List<E> readList<E>(E f(), {bool emptyAsNull: false});
/// Reads a boolean value from this data source.
bool readBool();
/// Reads a non-negative 30 bit integer value from this data source.
int readInt();
/// Reads a potentially `null` non-negative integer value from this data
/// source.
///
/// This is a convenience method to be used together with
/// [DataSink.writeIntOrNull].
int readIntOrNull();
/// Reads a string value from this data source.
String readString();
/// Reads a potentially `null` string value from this data source.
///
/// This is a convenience method to be used together with
/// [DataSink.writeStringOrNull].
String readStringOrNull();
/// Reads a list of string values from this data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeStrings].
List<String> readStrings({bool emptyAsNull: false});
/// Reads a map from string values to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeStringMap].
Map<String, V> readStringMap<V>(V f(), {bool emptyAsNull: false});
/// Reads an enum value from the list of enum [values] from this data source.
///
/// The [values] argument is intended to be the static `.values` field on
/// enum classes, for instance:
///
/// enum Foo { bar, baz }
/// ...
/// Foo foo = source.readEnum(Foo.values);
///
E readEnum<E>(List<E> values);
/// Reads a URI value from this data source.
Uri readUri();
/// Reads a reference to a kernel library node from this data source.
ir.Library readLibraryNode();
/// Reads a reference to a kernel class node from this data source.
ir.Class readClassNode();
/// Reads a reference to a kernel class node from this data source.
ir.Typedef readTypedefNode();
/// Reads a reference to a kernel member node from this data source.
ir.Member readMemberNode();
/// Reads a list of references to kernel member nodes from this data source.
/// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeMemberNodes].
List<ir.Member> readMemberNodes<E extends ir.Member>(
{bool emptyAsNull: false});
/// Reads a map from kernel member nodes to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeMemberNodeMap].
Map<K, V> readMemberNodeMap<K extends ir.Member, V>(V f(),
{bool emptyAsNull: false});
/// Reads a kernel name node from this data source.
ir.Name readName();
/// Reads a kernel library dependency node from this data source.
ir.LibraryDependency readLibraryDependencyNode();
/// Reads a potentially `null` kernel library dependency node from this data
/// source.
ir.LibraryDependency readLibraryDependencyNodeOrNull();
/// Reads a reference to a kernel tree node from this data source.
ir.TreeNode readTreeNode();
/// Reads a reference to a potentially `null` kernel tree node from this data
/// source.
ir.TreeNode readTreeNodeOrNull();
/// Reads a list of references to kernel tree nodes from this data source.
/// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeTreeNodes].
List<E> readTreeNodes<E extends ir.TreeNode>({bool emptyAsNull: false});
/// Reads a map from kernel tree nodes to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeTreeNodeMap].
Map<K, V> readTreeNodeMap<K extends ir.TreeNode, V>(V f(),
{bool emptyAsNull: false});
/// Reads a reference to a kernel tree node in the known [context] from this
/// data source.
ir.TreeNode readTreeNodeInContext();
/// Reads a reference to a potentially `null` kernel tree node in the known
/// [context] from this data source.
ir.TreeNode readTreeNodeOrNullInContext();
/// Reads a list of references to kernel tree nodes in the known [context]
/// from this data source. If [emptyAsNull] is `true`, `null` is returned
/// instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeTreeNodesInContext].
List<E> readTreeNodesInContext<E extends ir.TreeNode>(
{bool emptyAsNull: false});
/// Reads a map from kernel tree nodes to [V] values in the known [context]
/// from this data source, calling [f] to read each value from the data
/// source. If [emptyAsNull] is `true`, `null` is returned instead of an empty
/// map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeTreeNodeMapInContext].
Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f(),
{bool emptyAsNull: false});
/// Reads a reference to a kernel type parameter node from this data source.
ir.TypeParameter readTypeParameterNode();
/// Reads a list of references to kernel type parameter nodes from this data
/// source. If [emptyAsNull] is `true`, `null` is returned instead of an empty
/// list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeTypeParameterNodes].
List<ir.TypeParameter> readTypeParameterNodes({bool emptyAsNull: false});
/// Reads a type from this data source. If [allowNull], the returned type is
/// allowed to be `null`.
DartType readDartType({bool allowNull: false});
/// Reads a list of types from this data source. If [emptyAsNull] is `true`,
/// `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeDartTypes].
List<DartType> readDartTypes({bool emptyAsNull: false});
/// Reads a kernel type node from this data source. If [allowNull], the
/// returned type is allowed to be `null`.
ir.DartType readDartTypeNode({bool allowNull: false});
/// Reads a list of kernel type nodes from this data source. If [emptyAsNull]
/// is `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeDartTypeNodes].
List<ir.DartType> readDartTypeNodes({bool emptyAsNull: false});
/// Reads a source span from this data source.
SourceSpan readSourceSpan();
/// Reads a reference to an indexed library from this data source.
IndexedLibrary readLibrary();
/// Reads a reference to a potentially `null` indexed library from this data
/// source.
IndexedLibrary readLibraryOrNull();
Map<K, V> readLibraryMap<K extends LibraryEntity, V>(V f(),
{bool emptyAsNull: false});
/// Reads a reference to an indexed class from this data source.
IndexedClass readClass();
/// Reads a reference to a potentially `null` indexed class from this data
/// source.
IndexedClass readClassOrNull();
/// Reads a list of references to indexed classes from this data source.
/// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeClasses].
List<E> readClasses<E extends ClassEntity>({bool emptyAsNull: false});
/// Reads a map from indexed classes to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeClassMap].
Map<K, V> readClassMap<K extends ClassEntity, V>(V f(),
{bool emptyAsNull: false});
/// Reads a reference to an indexed typedef from this data source.
IndexedTypedef readTypedef();
/// Reads a reference to an indexed member from this data source.
IndexedMember readMember();
/// Reads a reference to a potentially `null` indexed member from this data
/// source.
IndexedMember readMemberOrNull();
/// Reads a list of references to indexed members from this data source.
/// If [emptyAsNull] is `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeMembers].
List<E> readMembers<E extends MemberEntity>({bool emptyAsNull: false});
/// Reads a map from indexed members to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeMemberMap].
Map<K, V> readMemberMap<K extends MemberEntity, V>(V f(MemberEntity member),
{bool emptyAsNull: false});
/// Reads a reference to a local from this data source.
Local readLocal();
/// Reads a reference to a potentially `null` local from this data source.
Local readLocalOrNull();
/// Reads a list of references to locals from this data source. If
/// [emptyAsNull] is `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeLocals].
List<E> readLocals<E extends Local>({bool emptyAsNull: false});
/// Reads a map from locals to [V] values from this data source, calling [f]
/// to read each value from the data source. If [emptyAsNull] is `true`,
/// `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeLocalMap].
Map<K, V> readLocalMap<K extends Local, V>(V f(), {bool emptyAsNull: false});
/// Reads a constant value from this data source.
ConstantValue readConstant();
/// Reads a potentially `null` constant value from this data source.
ConstantValue readConstantOrNull();
/// Reads a double value from this data source.
double readDoubleValue();
/// Reads an integer of arbitrary value from this data source.
///
/// This is should only when the value is not known to be a non-negative
/// 30 bit integer. Otherwise [readInt] should be used.
int readIntegerValue();
/// Reads a list of constant values from this data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeConstants].
List<E> readConstants<E extends ConstantValue>({bool emptyAsNull: false});
/// Reads a map from constant values to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeConstantMap].
Map<K, V> readConstantMap<K extends ConstantValue, V>(V f(),
{bool emptyAsNull: false});
/// Reads a import from this data source.
ImportEntity readImport();
/// Reads a potentially `null` import from this data source.
ImportEntity readImportOrNull();
/// Reads a list of imports from this data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty list.
///
/// This is a convenience method to be used together with
/// [DataSink.writeImports].
List<ImportEntity> readImports({bool emptyAsNull: false});
/// Reads a map from imports to [V] values from this data source,
/// calling [f] to read each value from the data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty map.
///
/// This is a convenience method to be used together with
/// [DataSink.writeImportMap].
Map<ImportEntity, V> readImportMap<V>(V f(), {bool emptyAsNull: false});
/// Reads an [AbstractValue] from this data source.
///
/// This feature is only available a [CodegenReader] has been registered.
AbstractValue readAbstractValue();
/// Reads a reference to an [OutputUnit] from this data source.
///
/// This feature is only available a [CodegenReader] has been registered.
OutputUnit readOutputUnitReference();
/// Reads a [js.Node] value from this data source.
///
/// This feature is only available a [CodegenReader] has been registered.
js.Node readJsNode();
/// Reads a potentially `null` [js.Node] value from this data source.
///
/// This feature is only available a [CodegenReader] has been registered.
js.Node readJsNodeOrNull();
}
/// Interface used for looking up entities by index during deserialization.
abstract class EntityLookup {
/// Returns the indexed library corresponding to [index].
IndexedLibrary getLibraryByIndex(int index);
/// Returns the indexed class corresponding to [index].
IndexedClass getClassByIndex(int index);
/// Returns the indexed typedef corresponding to [index].
IndexedTypedef getTypedefByIndex(int index);
/// Returns the indexed member corresponding to [index].
IndexedMember getMemberByIndex(int index);
/// Returns the indexed type variable corresponding to [index].
IndexedTypeVariable getTypeVariableByIndex(int index);
}
/// Decoding strategy for entity references.
class EntityReader {
const EntityReader();
IndexedLibrary readLibraryFromDataSource(
DataSource source, EntityLookup entityLookup) {
return entityLookup.getLibraryByIndex(source.readInt());
}
IndexedClass readClassFromDataSource(
DataSource source, EntityLookup entityLookup) {
return entityLookup.getClassByIndex(source.readInt());
}
IndexedTypedef readTypedefFromDataSource(
DataSource source, EntityLookup entityLookup) {
return entityLookup.getTypedefByIndex(source.readInt());
}
IndexedMember readMemberFromDataSource(
DataSource source, EntityLookup entityLookup) {
return entityLookup.getMemberByIndex(source.readInt());
}
IndexedTypeVariable readTypeVariableFromDataSource(
DataSource source, EntityLookup entityLookup) {
return entityLookup.getTypeVariableByIndex(source.readInt());
}
}
/// Encoding strategy for entity references.
class EntityWriter {
const EntityWriter();
void writeLibraryToDataSink(DataSink sink, IndexedLibrary value) {
sink.writeInt(value.libraryIndex);
}
void writeClassToDataSink(DataSink sink, IndexedClass value) {
sink.writeInt(value.classIndex);
}
void writeTypedefToDataSink(DataSink sink, IndexedTypedef value) {
sink.writeInt(value.typedefIndex);
}
void writeMemberToDataSink(DataSink sink, IndexedMember value) {
sink.writeInt(value.memberIndex);
}
void writeTypeVariableToDataSink(DataSink sink, IndexedTypeVariable value) {
sink.writeInt(value.typeVariableIndex);
}
}
/// Interface used for looking up locals by index during deserialization.
abstract class LocalLookup {
Local getLocalByIndex(MemberEntity memberContext, int index);
}
/// Interface used for reading codegen only data during deserialization.
abstract class CodegenReader {
AbstractValue readAbstractValue(DataSource source);
OutputUnit readOutputUnitReference(DataSource source);
js.Node readJsNode(DataSource source);
}
/// Interface used for writing codegen only data during serialization.
abstract class CodegenWriter {
void writeAbstractValue(DataSink sink, AbstractValue value);
void writeOutputUnitReference(DataSink sink, OutputUnit value);
void writeJsNode(DataSink sink, js.Node node);
}