// 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.

part of 'serialization.dart';

/// Serialization writer
///
/// To be used with [DataSourceReader] to read and write serialized data.
/// Serialization format is deferred to provided [DataSink].
class DataSinkWriter {
  final DataSink _sinkWriter;

  final bool enableDeferredStrategy;

  /// If `true`, serialization of every data kind is preceded by a [DataKind]
  /// value.
  ///
  /// This is used for debugging data inconsistencies between serialization
  /// and deserialization.
  final bool useDataKinds;

  DataSourceIndices? importedIndices;

  /// Visitor used for serializing [ir.DartType]s.
  late final DartTypeNodeWriter _dartTypeNodeWriter;

  /// Stack of tags used when [useDataKinds] is `true` to help debugging section
  /// inconsistencies between serialization and deserialization.
  List<String>? _tags;

  /// Map of [MemberData] object for serialized kernel member nodes.
  final Map<ir.Member, MemberData> _memberData = {};

  late final IndexedSink<String> _stringIndex;
  late final IndexedSink<Uri> _uriIndex;
  late final IndexedSink<ir.Member> _memberNodeIndex;
  late final IndexedSink<ImportEntity> _importIndex;
  late final IndexedSink<ConstantValue> _constantIndex;

  final Map<Type, IndexedSink> _generalCaches = {};

  EntityWriter _entityWriter = const EntityWriter();
  late final CodegenWriter _codegenWriter;

  final Map<String, int>? tagFrequencyMap;

  ir.Member? _currentMemberContext;
  MemberData? _currentMemberData;

  IndexedSink<T> _createUnorderedSink<T>() {
    final indices = importedIndices;
    if (indices == null) return UnorderedIndexedSink<T>(this);
    final sourceInfo = indices.caches[T];
    if (sourceInfo == null) {
      return UnorderedIndexedSink<T>(this,
          startOffset: indices.previousSourceReader?.endOffset);
    }
    Map<T, int> cacheCopy = Map.from(sourceInfo.cache);
    return UnorderedIndexedSink<T>(this,
        cache: cacheCopy, startOffset: indices.previousSourceReader?.endOffset);
  }

  IndexedSink<T> _createSink<T>() {
    final indices = importedIndices;
    if (indices == null || !indices.caches.containsKey(T)) {
      return OrderedIndexedSink<T>(_sinkWriter);
    } else {
      Map<T, int> cacheCopy = Map.from(indices.caches[T]!.cache);
      return OrderedIndexedSink<T>(_sinkWriter, cache: cacheCopy);
    }
  }

  DataSinkWriter(this._sinkWriter, CompilerOptions options,
      {this.useDataKinds = false, this.tagFrequencyMap, this.importedIndices})
      : enableDeferredStrategy =
            options.features.deferredSerialization.isEnabled {
    _dartTypeNodeWriter = DartTypeNodeWriter(this);
    if (!enableDeferredStrategy) {
      _stringIndex = _createSink<String>();
      _uriIndex = _createSink<Uri>();
      _memberNodeIndex = _createSink<ir.Member>();
      _importIndex = _createSink<ImportEntity>();
      _constantIndex = _createSink<ConstantValue>();
      return;
    }
    _stringIndex = _createUnorderedSink<String>();
    _uriIndex = _createUnorderedSink<Uri>();
    _memberNodeIndex = _createUnorderedSink<ir.Member>();
    _importIndex = _createUnorderedSink<ImportEntity>();
    _constantIndex = _createUnorderedSink<ConstantValue>();
  }

  /// 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 => _sinkWriter.length;

  /// Flushes any pending data and closes this data sink.
  ///
  /// The data sink can no longer be written to after closing.
  void close() {
    _sinkWriter.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) {
    tagFrequencyMap?.update(tag, (count) => count + 1, ifAbsent: () => 1);
    if (useDataKinds) {
      (_tags ??= <String>[]).add(tag);
      _sinkWriter.beginTag(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) {
    if (useDataKinds) {
      _sinkWriter.endTag(tag);

      String existingTag = _tags!.removeLast();
      assert(existingTag == tag,
          "Unexpected tag end. Expected $existingTag, found $tag.");
    }
  }

  void writeDeferrable(void f()) {
    if (enableDeferredStrategy) {
      _sinkWriter.writeDeferred(f);
    } else {
      f();
    }
  }

  /// 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)) {
    IndexedSink sink = _generalCaches[E] ??=
        (enableDeferredStrategy ? _createUnorderedSink<E>() : _createSink<E>());
    sink.write(value, (v) => f(v));
  }

  /// 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
  /// [DataSourceReader.readValueOrNull].
  void writeValueOrNull<E>(E? value, void f(E value)) {
    writeBool(value != null);
    if (value != null) {
      f(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
  /// [DataSourceReader.readList].
  void writeList<E>(Iterable<E>? values, void f(E value),
      {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      values.forEach(f);
    }
  }

  /// Writes the boolean [value] to this data sink.
  void writeBool(bool value) {
    assert((value as dynamic) != null); // TODO(48820): Remove when sound.
    _writeDataKind(DataKind.bool);
    _writeBool(value);
  }

  void _writeBool(bool value) {
    _sinkWriter.writeInt(value ? 1 : 0);
  }

  /// Writes the non-negative 30 bit integer [value] to this data sink.
  void writeInt(int value) {
    assert((value as dynamic) != null); // TODO(48820): Remove when sound.
    assert(value >= 0 && value >> 30 == 0);
    _writeDataKind(DataKind.uint30);
    _sinkWriter.writeInt(value);
  }

  /// Writes the potentially `null` non-negative [value] to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readIntOrNull].
  void writeIntOrNull(int? value) {
    writeBool(value != null);
    if (value != null) {
      writeInt(value);
    }
  }

  /// Writes the string [value] to this data sink.
  void writeString(String value) {
    assert((value as dynamic) != null); // TODO(48820): Remove when sound.
    _writeDataKind(DataKind.string);
    _writeString(value);
  }

  void _writeString(String value) {
    _stringIndex.write(value, _sinkWriter.writeString);
  }

  /// Writes the potentially `null` string [value] to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readStringOrNull].
  void writeStringOrNull(String? value) {
    writeBool(value != null);
    if (value != null) {
      writeString(value);
    }
  }

  /// 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
  /// [DataSourceReader.readStringMap].
  void writeStringMap<V>(Map<String, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((String key, V value) {
        writeString(key);
        f(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
  /// [DataSourceReader.readStrings].
  void writeStrings(Iterable<String>? values, {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (String value in values) {
        writeString(value);
      }
    }
  }

  /// 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) {
    _writeDataKind(DataKind.enumValue);
    _sinkWriter.writeEnum(value);
  }

  /// Writes the URI [value] to this data sink.
  void writeUri(Uri value) {
    assert((value as dynamic) != null); // TODO(48820): Remove when sound.
    _writeDataKind(DataKind.uri);
    _writeUri(value);
  }

  void _writeUri(Uri value) {
    _uriIndex.write(value, _doWriteUri);
  }

  void _doWriteUri(Uri value) {
    _writeString(value.toString());
  }

  /// Writes a reference to the kernel library node [value] to this data sink.
  void writeLibraryNode(ir.Library value) {
    _writeDataKind(DataKind.libraryNode);
    _writeLibraryNode(value);
  }

  void _writeLibraryNode(ir.Library value) {
    _writeUri(value.importUri);
  }

  /// Writes a reference to the kernel class node [value] to this data sink.
  void writeClassNode(ir.Class value) {
    _writeDataKind(DataKind.classNode);
    _writeClassNode(value);
  }

  void _writeClassNode(ir.Class value) {
    _writeLibraryNode(value.enclosingLibrary);
    _writeString(value.name);
  }

  /// Writes a reference to the kernel typedef node [value] to this data sink.
  void writeTypedefNode(ir.Typedef value) {
    _writeDataKind(DataKind.typedefNode);
    _writeTypedefNode(value);
  }

  void _writeTypedefNode(ir.Typedef value) {
    _writeLibraryNode(value.enclosingLibrary);
    _writeString(value.name);
  }

  /// Writes a reference to the kernel member node [value] to this data sink.
  void writeMemberNode(ir.Member value) {
    _writeDataKind(DataKind.memberNode);
    _writeMemberNode(value);
  }

  void _writeMemberNode(ir.Member value) {
    _memberNodeIndex.write(value, _writeMemberNodeInternal);
  }

  void _writeMemberNodeInternal(ir.Member value) {
    ir.Class? cls = value.enclosingClass;
    if (cls != null) {
      _sinkWriter.writeEnum(MemberContextKind.cls);
      _writeClassNode(cls);
      _writeString(computeMemberName(value));
    } else {
      _sinkWriter.writeEnum(MemberContextKind.library);
      _writeLibraryNode(value.enclosingLibrary);
      _writeString(computeMemberName(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
  /// [DataSourceReader.readMemberNodes].
  void writeMemberNodes(Iterable<ir.Member>? values, {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ir.Member value in values) {
        writeMemberNode(value);
      }
    }
  }

  /// 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
  /// [DataSourceReader.readMemberNodeMap].
  void writeMemberNodeMap<V>(Map<ir.Member, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((ir.Member key, V value) {
        writeMemberNode(key);
        f(value);
      });
    }
  }

  /// Writes a kernel name node to this data sink.
  void writeName(ir.Name value) {
    writeString(value.text);
    writeValueOrNull(value.library, writeLibraryNode);
  }

  /// Writes a kernel library dependency node [value] to this data sink.
  void writeLibraryDependencyNode(ir.LibraryDependency value) {
    final library = value.parent as ir.Library;
    writeLibraryNode(library);
    writeInt(library.dependencies.indexOf(value));
  }

  /// Writes a potentially `null` kernel library dependency node [value] to
  /// this data sink.
  void writeLibraryDependencyNodeOrNull(ir.LibraryDependency? value) {
    writeValueOrNull(value, writeLibraryDependencyNode);
  }

  /// Writes a reference to the kernel tree node [value] to this data sink.
  void writeTreeNode(ir.TreeNode value) {
    _writeDataKind(DataKind.treeNode);
    _writeTreeNode(value, null);
  }

  void _writeTreeNode(ir.TreeNode value, MemberData? memberData) {
    if (value is ir.Class) {
      _sinkWriter.writeEnum(_TreeNodeKind.cls);
      _writeClassNode(value);
    } else if (value is ir.Member) {
      _sinkWriter.writeEnum(_TreeNodeKind.member);
      _writeMemberNode(value);
    } else if (value is ir.VariableDeclaration &&
        value.parent is ir.FunctionDeclaration) {
      _sinkWriter.writeEnum(_TreeNodeKind.functionDeclarationVariable);
      _writeTreeNode(value.parent!, memberData);
    } else if (value is ir.FunctionNode) {
      _sinkWriter.writeEnum(_TreeNodeKind.functionNode);
      _writeFunctionNode(value, memberData);
    } else if (value is ir.TypeParameter) {
      _sinkWriter.writeEnum(_TreeNodeKind.typeParameter);
      _writeTypeParameter(value, memberData);
    } else if (value is ConstantReference) {
      _sinkWriter.writeEnum(_TreeNodeKind.constant);
      memberData ??= _getMemberData(value.expression);
      _writeTreeNode(value.expression, memberData);
      int index =
          memberData.getIndexByConstant(value.expression, value.constant);
      _sinkWriter.writeInt(index);
    } else {
      _sinkWriter.writeEnum(_TreeNodeKind.node);
      memberData ??= _getMemberData(value);
      int index = memberData.getIndexByTreeNode(value);
      _sinkWriter.writeInt(index);
    }
  }

  /// 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
  /// [DataSourceReader.readTreeNodeOrNull].
  void writeTreeNodeOrNull(ir.TreeNode? value) {
    writeBool(value != null);
    if (value != null) {
      writeTreeNode(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
  /// [DataSourceReader.readTreeNodes].
  void writeTreeNodes(Iterable<ir.TreeNode>? values, {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ir.TreeNode value in values) {
        writeTreeNode(value);
      }
    }
  }

  /// 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
  /// [DataSourceReader.readTreeNodeMap].
  void writeTreeNodeMap<V>(Map<ir.TreeNode, V> map, void f(V value)) {
    writeInt(map.length);
    map.forEach((ir.TreeNode key, V value) {
      writeTreeNode(key);
      f(value);
    });
  }

  /// Writes a reference to the kernel tree node [value] in the known [context]
  /// to this data sink.
  void writeTreeNodeInContext(ir.TreeNode value) {
    writeTreeNodeInContextInternal(value, currentMemberData);
  }

  void writeTreeNodeInContextInternal(
      ir.TreeNode value, MemberData memberData) {
    _writeDataKind(DataKind.treeNode);
    _writeTreeNode(value, memberData);
  }

  /// 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
  /// [DataSourceReader.readTreeNodeOrNullInContext].
  void writeTreeNodeOrNullInContext(ir.TreeNode? value) {
    writeBool(value != null);
    if (value != null) {
      writeTreeNodeInContextInternal(value, currentMemberData);
    }
  }

  /// 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
  /// [DataSourceReader.readTreeNodesInContext].
  void writeTreeNodesInContext(Iterable<ir.TreeNode>? values,
      {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ir.TreeNode value in values) {
        writeTreeNodeInContextInternal(value, currentMemberData);
      }
    }
  }

  /// 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
  /// [DataSourceReader.readTreeNodeMapInContext].
  void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((ir.TreeNode key, V value) {
        writeTreeNodeInContextInternal(key, currentMemberData);
        f(value);
      });
    }
  }

  /// Writes a reference to the kernel type parameter node [value] to this data
  /// sink.
  void writeTypeParameterNode(ir.TypeParameter value) {
    _writeDataKind(DataKind.typeParameterNode);
    _writeTypeParameter(value, null);
  }

  void _writeTypeParameter(ir.TypeParameter value, MemberData? memberData) {
    ir.TreeNode parent = value.parent!;
    if (parent is ir.Class) {
      _sinkWriter.writeEnum(_TypeParameterKind.cls);
      _writeClassNode(parent);
      _sinkWriter.writeInt(parent.typeParameters.indexOf(value));
    } else if (parent is ir.FunctionNode) {
      _sinkWriter.writeEnum(_TypeParameterKind.functionNode);
      _writeFunctionNode(parent, memberData);
      _sinkWriter.writeInt(parent.typeParameters.indexOf(value));
    } else {
      throw UnsupportedError(
          "Unsupported TypeParameter parent ${parent.runtimeType}");
    }
  }

  /// 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
  /// [DataSourceReader.readTypeParameterNodes].
  void writeTypeParameterNodes(Iterable<ir.TypeParameter> values) {
    writeInt(values.length);
    for (ir.TypeParameter value in values) {
      writeTypeParameterNode(value);
    }
  }

  /// Writes the type [value] to this data sink.
  void writeDartType(DartType value) {
    _writeDataKind(DataKind.dartType);
    value.writeToDataSink(this, []);
  }

  /// Writes the optional type [value] to this data sink.
  void writeDartTypeOrNull(DartType? value) {
    _writeDataKind(DataKind.dartType);
    if (value == null) {
      writeEnum(DartTypeKind.none);
    } else {
      value.writeToDataSink(this, []);
    }
  }

  /// Writes the types [values] to this data sink. If [values] is null, write a
  /// zero-length iterable.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readDartTypesOrNull].
  void writeDartTypesOrNull(Iterable<DartType>? values) {
    if (values == null) {
      writeInt(0);
    } else {
      writeDartTypes(values);
    }
  }

  /// Writes the types [values] to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readDartTypes].
  void writeDartTypes(Iterable<DartType> values) {
    writeInt(values.length);
    for (DartType value in values) {
      writeDartType(value);
    }
  }

  /// Writes the kernel type node [value] to this data sink.
  void writeDartTypeNode(ir.DartType /*!*/ value) {
    _writeDataKind(DataKind.dartTypeNode);
    _writeDartTypeNode(value, [], allowNull: false);
  }

  /// Writes the kernel type node [value] to this data sink, `null` permitted.
  void writeDartTypeNodeOrNull(ir.DartType? value) {
    _writeDataKind(DataKind.dartTypeNode);
    _writeDartTypeNode(value, [], allowNull: true);
  }

  void _writeDartTypeNode(
      ir.DartType? value, List<ir.TypeParameter> functionTypeVariables,
      {bool allowNull = false}) {
    if (value == null) {
      if (!allowNull) {
        throw UnsupportedError("Missing ir.DartType node is not allowed.");
      }
      writeEnum(DartTypeNodeKind.none);
    } else {
      value.accept1(_dartTypeNodeWriter, functionTypeVariables);
    }
  }

  /// 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
  /// [DataSourceReader.readDartTypeNodes].
  void writeDartTypeNodes(Iterable<ir.DartType>? values,
      {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ir.DartType value in values) {
        writeDartTypeNode(value);
      }
    }
  }

  /// Writes the source span [value] to this data sink.
  void writeSourceSpan(SourceSpan value) {
    _writeDataKind(DataKind.sourceSpan);
    _writeUri(value.uri);
    _sinkWriter.writeInt(value.begin);
    _sinkWriter.writeInt(value.end);
  }

  /// Writes a reference to the library entity [value] to this data sink.
  void writeLibrary(LibraryEntity value) {
    if (value is IndexedLibrary) {
      _entityWriter.writeLibraryToDataSink(this, value);
    } else {
      failedAt(value, 'Unexpected library entity type ${value.runtimeType}');
    }
  }

  /// Writes a reference to the potentially `null` library entities [value]
  /// to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readLibraryOrNull].
  void writeLibraryOrNull(LibraryEntity? value) {
    writeBool(value != null);
    if (value != null) {
      writeLibrary(value);
    }
  }

  /// Writes the [map] from references to library entities 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
  /// [DataSourceReader.readLibraryMap].
  void writeLibraryMap<V>(Map<LibraryEntity, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((LibraryEntity library, V value) {
        writeLibrary(library);
        f(value);
      });
    }
  }

  /// Writes a reference to the class entity [value] to this data sink.
  void writeClass(ClassEntity value) {
    if (value is IndexedClass) {
      _entityWriter.writeClassToDataSink(this, value);
    } else {
      failedAt(value, 'Unexpected class entity type ${value.runtimeType}');
    }
  }

  /// Writes a reference to the potentially `null` class entity [value]
  /// to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readClassOrNull].
  void writeClassOrNull(ClassEntity? value) {
    writeBool(value != null);
    if (value != null) {
      writeClass(value);
    }
  }

  /// Writes references to the class entity [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
  /// [DataSourceReader.readClasses].
  void writeClasses(Iterable<ClassEntity>? values, {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ClassEntity value in values) {
        writeClass(value);
      }
    }
  }

  /// Writes the [map] from references to class entities 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
  /// [DataSourceReader.readClassMap].
  void writeClassMap<V>(Map<ClassEntity, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((ClassEntity cls, V value) {
        writeClass(cls);
        f(value);
      });
    }
  }

  /// Writes a reference to the member entity [value] to this data sink.
  void writeMember(MemberEntity value) {
    if (value is IndexedMember) {
      _entityWriter.writeMemberToDataSink(this, value);
    } else {
      failedAt(value, 'Unexpected member entity type ${value.runtimeType}');
    }
  }

  /// Writes a reference to the potentially `null` member entities [value]
  /// to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readMemberOrNull].
  void writeMemberOrNull(MemberEntity? value) {
    writeBool(value != null);
    if (value != null) {
      writeMember(value);
    }
  }

  /// Writes references to the member entities [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
  /// [DataSourceReader.readMembers].
  void writeMembers(Iterable<MemberEntity>? values, {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (MemberEntity value in values) {
        writeMember(value);
      }
    }
  }

  /// Writes the [map] from references to member entities 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
  /// [DataSourceReader.readMemberMap].
  void writeMemberMap<V>(
      Map<MemberEntity, V>? map, void f(MemberEntity member, V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((MemberEntity member, V value) {
        writeMember(member);
        f(member, value);
      });
    }
  }

  /// Writes a reference to the type variable entity [value] to this data sink.
  void writeTypeVariable(TypeVariableEntity value) {
    if (value is IndexedTypeVariable) {
      _entityWriter.writeTypeVariableToDataSink(this, value);
    } else {
      failedAt(
          value, 'Unexpected type variable entity type ${value.runtimeType}');
    }
  }

  /// Writes the [map] from references to type variable entites 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
  /// [DataSourceReader.readTypeVariableMap].
  void writeTypeVariableMap<V>(
      Map<TypeVariableEntity, V> map, void f(V value)) {
    writeInt(map.length);
    map.forEach((TypeVariableEntity key, V value) {
      writeTypeVariable(key);
      f(value);
    });
  }

  /// Writes a reference to the local [value] to this data sink.
  void writeLocal(Local local) {
    if (local is JLocal) {
      writeEnum(LocalKind.jLocal);
      writeMember(local.memberContext);
      writeInt(local.localIndex);
    } else if (local is ThisLocal) {
      writeEnum(LocalKind.thisLocal);
      writeClass(local.enclosingClass);
    } else if (local is BoxLocal) {
      writeEnum(LocalKind.boxLocal);
      writeClass(local.container);
    } else if (local is AnonymousClosureLocal) {
      writeEnum(LocalKind.anonymousClosureLocal);
      writeClass(local.closureClass);
    } else if (local is TypeVariableLocal) {
      writeEnum(LocalKind.typeVariableLocal);
      writeTypeVariable(local.typeVariable);
    } else {
      throw UnsupportedError("Unsupported local ${local.runtimeType}");
    }
  }

  /// Writes a reference to the potentially `null` local [value]
  /// to this data sink.
  ///
  /// This is a convenience method to be used together with
  /// [DataSourceReader.readLocalOrNull].
  void writeLocalOrNull(Local? value) {
    writeBool(value != null);
    if (value != null) {
      writeLocal(value);
    }
  }

  /// 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
  /// [DataSourceReader.readLocalMap].
  void writeLocalMap<V>(Map<Local, V> map, void f(V value)) {
    writeInt(map.length);
    map.forEach((Local key, V value) {
      writeLocal(key);
      f(value);
    });
  }

  /// Writes the constant [value] to this data sink.
  void writeConstant(ConstantValue value) {
    _writeDataKind(DataKind.constant);
    _writeConstant(value);
  }

  void _writeConstant(ConstantValue value) {
    _constantIndex.write(value, _writeConstantInternal);
  }

  void _writeConstantInternal(ConstantValue value) {
    _sinkWriter.writeEnum(value.kind);
    switch (value.kind) {
      case ConstantValueKind.BOOL:
        final constant = value as BoolConstantValue;
        writeBool(constant.boolValue);
        break;
      case ConstantValueKind.INT:
        final constant = value as IntConstantValue;
        _writeBigInt(constant.intValue);
        break;
      case ConstantValueKind.DOUBLE:
        final constant = value as DoubleConstantValue;
        _writeDoubleValue(constant.doubleValue);
        break;
      case ConstantValueKind.STRING:
        final constant = value as StringConstantValue;
        writeString(constant.stringValue);
        break;
      case ConstantValueKind.NULL:
        break;
      case ConstantValueKind.FUNCTION:
        final constant = value as FunctionConstantValue;
        writeMember(constant.element);
        writeDartType(constant.type);
        break;
      case ConstantValueKind.LIST:
        final constant = value as ListConstantValue;
        writeDartType(constant.type);
        writeConstants(constant.entries);
        break;
      case ConstantValueKind.SET:
        final constant = value as constant_system.JavaScriptSetConstant;
        writeDartType(constant.type);
        writeConstant(constant.entries);
        break;
      case ConstantValueKind.MAP:
        final constant = value as constant_system.JavaScriptMapConstant;
        writeDartType(constant.type);
        writeConstant(constant.keyList);
        writeConstants(constant.values);
        writeBool(constant.onlyStringKeys);
        break;
      case ConstantValueKind.CONSTRUCTED:
        final constant = value as ConstructedConstantValue;
        writeDartType(constant.type);
        writeMemberMap(constant.fields,
            (MemberEntity member, ConstantValue value) => writeConstant(value));
        break;
      case ConstantValueKind.TYPE:
        final constant = value as TypeConstantValue;
        writeDartType(constant.representedType);
        writeDartType(constant.type);
        break;
      case ConstantValueKind.INSTANTIATION:
        final constant = value as InstantiationConstantValue;
        writeDartTypes(constant.typeArguments);
        writeConstant(constant.function);
        break;
      case ConstantValueKind.NON_CONSTANT:
        break;
      case ConstantValueKind.INTERCEPTOR:
        final constant = value as InterceptorConstantValue;
        writeClass(constant.cls);
        break;
      case ConstantValueKind.DEFERRED_GLOBAL:
        final constant = value as DeferredGlobalConstantValue;
        writeConstant(constant.referenced);
        writeOutputUnitReference(constant.unit);
        break;
      case ConstantValueKind.DUMMY_INTERCEPTOR:
        break;
      case ConstantValueKind.LATE_SENTINEL:
        break;
      case ConstantValueKind.UNREACHABLE:
        break;
      case ConstantValueKind.JS_NAME:
        final constant = value as JsNameConstantValue;
        writeJsNode(constant.name);
        break;
    }
  }

  /// Writes the potentially `null` constant [value] to this data sink.
  void writeConstantOrNull(ConstantValue? value) {
    writeBool(value != null);
    if (value != null) {
      writeConstant(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
  /// [DataSourceReader.readConstants].
  void writeConstants(Iterable<ConstantValue>? values,
      {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ConstantValue value in values) {
        writeConstant(value);
      }
    }
  }

  /// 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
  /// [DataSourceReader.readConstantMap].
  void writeConstantMap<V>(Map<ConstantValue, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((ConstantValue key, V value) {
        writeConstant(key);
        f(value);
      });
    }
  }

  /// Writes a double value to this data sink.
  void writeDoubleValue(double value) {
    _writeDataKind(DataKind.double);
    _writeDoubleValue(value);
  }

  void _writeDoubleValue(double value) {
    ByteData data = ByteData(8);
    data.setFloat64(0, value);
    writeInt(data.getUint16(0));
    writeInt(data.getUint16(2));
    writeInt(data.getUint16(4));
    writeInt(data.getUint16(6));
  }

  /// 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) {
    _writeDataKind(DataKind.int);
    _writeBigInt(BigInt.from(value));
  }

  void _writeBigInt(BigInt value) {
    writeString(value.toString());
  }

  /// Writes the import [value] to this data sink.
  void writeImport(ImportEntity value) {
    _writeDataKind(DataKind.import);
    _writeImport(value);
  }

  void _writeImport(ImportEntity value) {
    _importIndex.write(value, _writeImportInternal);
  }

  void _writeImportInternal(ImportEntity value) {
    // TODO(johnniwinther): Do we need to serialize non-deferred imports?
    writeStringOrNull(value.name);
    _writeUri(value.uri);
    _writeUri(value.enclosingLibraryUri);
    _writeBool(value.isDeferred);
  }

  /// Writes the potentially `null` import [value] to this data sink.
  void writeImportOrNull(ImportEntity? value) {
    writeBool(value != null);
    if (value != null) {
      writeImport(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
  /// [DataSourceReader.readImports].
  void writeImports(Iterable<ImportEntity>? values, {bool allowNull = false}) {
    if (values == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(values.length);
      for (ImportEntity value in values) {
        writeImport(value);
      }
    }
  }

  /// 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
  /// [DataSourceReader.readImportMap].
  void writeImportMap<V>(Map<ImportEntity, V>? map, void f(V value),
      {bool allowNull = false}) {
    if (map == null) {
      assert(allowNull);
      writeInt(0);
    } else {
      writeInt(map.length);
      map.forEach((ImportEntity key, V value) {
        writeImport(key);
        f(value);
      });
    }
  }

  /// Writes an abstract [value] to this data sink.
  ///
  /// This feature is only available a [CodegenWriter] has been registered.
  void writeAbstractValue(AbstractValue value) {
    _codegenWriter.writeAbstractValue(this, 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) {
    _codegenWriter.writeOutputUnitReference(this, 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) {
    _codegenWriter.writeJsNode(this, 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) {
    writeBool(value != null);
    if (value != null) {
      writeJsNode(value);
    }
  }

  /// Writes TypeRecipe [value] to this data sink.
  ///
  /// This feature is only available a [CodegenWriter] has been registered.
  void writeTypeRecipe(TypeRecipe value) {
    _codegenWriter.writeTypeRecipe(this, value);
  }

  /// Register an [EntityWriter] with this data sink for non-default encoding
  /// of entity references.
  void registerEntityWriter(EntityWriter writer) {
    assert((writer as dynamic) != null); // TODO(48820): Remove when sound.
    _entityWriter = writer;
  }

  /// Register a [CodegenWriter] with this data sink to support serialization
  /// of codegen only data.
  void registerCodegenWriter(CodegenWriter writer) {
    assert((writer as dynamic) != null); // TODO(48820): Remove when sound.
    _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 context, void f()) {
    ir.Member? oldMemberContext = _currentMemberContext;
    MemberData? oldMemberData = _currentMemberData;
    _currentMemberContext = context;
    _currentMemberData = null;
    f();
    _currentMemberData = oldMemberData;
    _currentMemberContext = oldMemberContext;
  }

  MemberData get currentMemberData {
    final currentMemberContext = _currentMemberContext!;
    return _currentMemberData ??=
        _memberData[currentMemberContext] ??= MemberData(currentMemberContext);
  }

  MemberData _getMemberData(ir.TreeNode node) {
    ir.TreeNode? member = node;
    while (member is! ir.Member) {
      if (member == null) {
        throw UnsupportedError("No enclosing member of TreeNode "
            "$node (${node.runtimeType})");
      }
      member = member.parent;
    }
    _writeMemberNode(member);
    return _memberData[member] ??= MemberData(member);
  }

  void _writeFunctionNode(ir.FunctionNode value, MemberData? memberData) {
    ir.TreeNode parent = value.parent!;
    if (parent is ir.Procedure) {
      _sinkWriter.writeEnum(_FunctionNodeKind.procedure);
      _writeMemberNode(parent);
    } else if (parent is ir.Constructor) {
      _sinkWriter.writeEnum(_FunctionNodeKind.constructor);
      _writeMemberNode(parent);
    } else if (parent is ir.FunctionExpression) {
      _sinkWriter.writeEnum(_FunctionNodeKind.functionExpression);
      _writeTreeNode(parent, memberData);
    } else if (parent is ir.FunctionDeclaration) {
      _sinkWriter.writeEnum(_FunctionNodeKind.functionDeclaration);
      _writeTreeNode(parent, memberData);
    } else {
      throw UnsupportedError(
          "Unsupported FunctionNode parent ${parent.runtimeType}");
    }
  }

  void _writeDataKind(DataKind kind) {
    if (useDataKinds) _sinkWriter.writeEnum(kind);
  }
}
