// 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 '../closure.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../deferred_load/output_unit.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';
import '../js_model/type_recipe.dart' show TypeRecipe;

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';

abstract class StringInterner {
  String internString(String string);
}

/// 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 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 indexed type variable [value] to this data sink.
  void writeTypeVariable(IndexedTypeVariable value);

  /// Writes the [map] from references to indexed type variables 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.readTypeVariableMap].
  void writeTypeVariableMap<V>(Map<IndexedTypeVariable, V> map, void f(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);

  /// Writes TypeRecipe [value] to this data sink.
  ///
  /// This feature is only available a [CodegenWriter] has been registered.
  void writeTypeRecipe(TypeRecipe 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());
}

/// Data class representing cache information for a given [T] which can be
/// passed from a [DataSource] to other [DataSource]s and [DataSink]s.
class DataSourceTypeIndices<E, T> {
  /// Reshapes a [List<T>] to a [Map<E, int>] using [_getValue].
  Map<E, int> _reshape() {
    var cache = <E, int>{};
    for (int i = 0; i < cacheAsList.length; i++) {
      cache[_getValue(cacheAsList[i])] = i;
    }
    return cache;
  }

  Map<E, int> get cache {
    return _cache ??= _reshape();
  }

  final List<T> cacheAsList;
  E Function(T value) _getValue;
  Map<E, int> _cache;

  /// Though [DataSourceTypeIndices] supports two types of caches. If the
  /// exported indices are imported into a [DataSource] then the [cacheAsList]
  /// will be used as is. If, however, the exported indices are imported into a
  /// [DataSink] then we need to reshape the [List<T>] into a [Map<E, int>]
  /// where [E] is either [T] or some value which can be derived from [T] by
  /// [_getValue].
  DataSourceTypeIndices(this.cacheAsList, [this._getValue]) {
    assert(_getValue != null || T == E);
    _getValue ??= (T t) => t as E;
  }
}

/// Data class representing the sum of all cache information for a given
/// [DataSource].
class DataSourceIndices {
  final Map<Type, DataSourceTypeIndices> caches = {};
}

/// Interface for deserialization.
abstract class DataSource {
  /// Exports [DataSourceIndices] for use in other [DataSource]s and
  /// [DataSink]s.
  DataSourceIndices exportIndices();

  /// 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 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 an indexed type variable from this data source.
  IndexedTypeVariable readTypeVariable();

  /// Reads a map from indexed type variable 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.writeTypeVariableMap].
  Map<K, V> readTypeVariableMap<K extends IndexedTypeVariable, V>(V f(),
      {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();

  /// Reads a [TypeRecipe] value from this data source.
  ///
  /// This feature is only available a [CodegenReader] has been registered.
  TypeRecipe readTypeRecipe();
}

/// 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 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());
  }

  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 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);
  TypeRecipe readTypeRecipe(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);
  void writeTypeRecipe(DataSink sink, TypeRecipe recipe);
}
