// Copyright (c) 2013, 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 "dart:io";

// Read the file in blocks of size 64k.
const int _blockSize = 64 * 1024;

// The maximum number of bytes to read in a single call to `read`.
//
// On Windows and macOS, it is an error to call
// `read/_read(fildes, buf, nbyte)` with `nbyte >= INT_MAX`.
//
// The POSIX specification states that the behavior of `read` is
// implementation-defined if `nbyte > SSIZE_MAX`. On Linux, the `read` will
// transfer at most 0x7ffff000 bytes and return the number of bytes actually.
// transfered.
//
// A smaller value has the advantage of:
// 1. making vm-service clients (e.g. debugger) more responsive
// 2. reducing memory overhead (since `readInto` copies memory)
//
// A bigger value reduces the number of system calls.
const int _maxReadSize = 16 * 1024 * 1024; // 16MB.

class _FileStream extends Stream<List<int>> {
  // Stream controller.
  late StreamController<Uint8List> _controller;

  // Information about the underlying file.
  String? _path;
  RandomAccessFile? _openedFile;
  int _position;
  int? _end;
  final Completer _closeCompleter = new Completer();

  // Has the stream been paused or unsubscribed?
  bool _unsubscribed = false;

  // Is there a read currently in progress?
  bool _readInProgress = true;
  bool _closed = false;

  bool _atEnd = false;

  _FileStream(this._path, int? position, this._end) : _position = position ?? 0;

  _FileStream.forStdin() : _position = 0;

  _FileStream.forRandomAccessFile(RandomAccessFile f)
    : _position = 0,
      _openedFile = f;

  StreamSubscription<Uint8List> listen(
    void onData(Uint8List event)?, {
    Function? onError,
    void onDone()?,
    bool? cancelOnError,
  }) {
    _controller = new StreamController<Uint8List>(
      sync: true,
      onListen: _start,
      onResume: _readBlock,
      onCancel: () {
        _unsubscribed = true;
        return _closeFile();
      },
    );
    return _controller.stream.listen(
      onData,
      onError: onError,
      onDone: onDone,
      cancelOnError: cancelOnError,
    );
  }

  Future _closeFile() {
    if (_readInProgress || _closed) {
      return _closeCompleter.future;
    }
    _closed = true;

    void done() {
      _closeCompleter.complete();
      _controller.close();
    }

    _openedFile!.close().catchError(_controller.addError).whenComplete(done);
    return _closeCompleter.future;
  }

  void _readBlock() {
    // Don't start a new read if one is already in progress.
    if (_readInProgress) return;
    if (_atEnd) {
      _closeFile();
      return;
    }
    _readInProgress = true;
    int readBytes = _blockSize;
    final end = _end;
    if (end != null) {
      readBytes = min(readBytes, end - _position);
      if (readBytes < 0) {
        _readInProgress = false;
        if (!_unsubscribed) {
          _controller.addError(new RangeError("Bad end position: $end"));
          _closeFile();
          _unsubscribed = true;
        }
        return;
      }
    }
    _openedFile!
        .read(readBytes)
        .then((block) {
          _readInProgress = false;
          if (_unsubscribed) {
            _closeFile();
            return;
          }
          _position += block.length;
          // read() may return less than `readBytes` if `_openFile` is a pipe or
          // terminal or if a signal is received. Only a empty return indicates
          // that the write side of the pipe is closed or that we are at the end
          // of a file.
          // See https://man7.org/linux/man-pages/man2/read.2.html
          if (block.length == 0 || (_end != null && _position == _end)) {
            _atEnd = true;
          }
          if (!_atEnd && !_controller.isPaused) {
            _readBlock();
          }
          if (block.length > 0) {
            _controller.add(block);
          }
          if (_atEnd) {
            _closeFile();
          }
        })
        .catchError((e, s) {
          if (!_unsubscribed) {
            _controller.addError(e, s);
            _closeFile();
            _unsubscribed = true;
          }
        });
  }

  void _start() {
    if (_position < 0) {
      _controller.addError(new RangeError("Bad start position: $_position"));
      _controller.close();
      _closeCompleter.complete();
      return;
    }

    void onReady(RandomAccessFile file) {
      _openedFile = file;
      _readInProgress = false;
      _readBlock();
    }

    void onOpenFile(RandomAccessFile file) {
      if (_position > 0) {
        file
            .setPosition(_position)
            .then(
              onReady,
              onError: (e, s) {
                _controller.addError(e, s);
                _readInProgress = false;
                _closeFile();
              },
            );
      } else {
        onReady(file);
      }
    }

    void openFailed(error, stackTrace) {
      _controller.addError(error, stackTrace);
      _controller.close();
      _closeCompleter.complete();
    }

    final path = _path;
    final openedFile = _openedFile;
    if (openedFile != null) {
      onOpenFile(openedFile);
    } else if (path != null) {
      new File(
        path,
      ).open(mode: FileMode.read).then(onOpenFile, onError: openFailed);
    } else {
      try {
        onOpenFile(_File._openStdioSync(0));
      } catch (e, s) {
        openFailed(e, s);
      }
    }
  }
}

class _FileStreamConsumer implements StreamConsumer<List<int>> {
  File? _file;
  Future<RandomAccessFile> _openFuture;

  _FileStreamConsumer(File file, FileMode mode)
    : _file = file,
      _openFuture = file.open(mode: mode);

  _FileStreamConsumer._fromStdio(int fd)
    : _openFuture = new Future.value(_File._openStdioSync(fd));

  _FileStreamConsumer.fromRandomAccessFile(RandomAccessFile f)
    : _openFuture = Future.value(f);

  Future<File?> addStream(Stream<List<int>> stream) {
    Completer<File?> completer = new Completer<File?>.sync();
    _openFuture
        .then((openedFile) {
          late StreamSubscription<List<int>> _subscription;
          void error(e, StackTrace stackTrace) {
            _subscription.cancel();
            openedFile.close();
            completer.completeError(e, stackTrace);
          }

          _subscription = stream.listen(
            (d) {
              _subscription.pause();
              try {
                openedFile
                    .writeFrom(d, 0, d.length)
                    .then((_) => _subscription.resume(), onError: error);
              } catch (e, stackTrace) {
                error(e, stackTrace);
              }
            },
            onDone: () {
              completer.complete(_file);
            },
            onError: error,
            cancelOnError: true,
          );
        })
        .catchError(completer.completeError);
    return completer.future;
  }

  Future<File?> close() =>
      _openFuture.then((openedFile) => openedFile.close()).then((_) => _file);
}

// Class for encapsulating the native implementation of files.
class _File extends FileSystemEntity implements File {
  final String _path;
  final Uint8List _rawPath;

  _File(String path)
    : _path = _checkNotNull(path, "path"),
      _rawPath = FileSystemEntity._toUtf8Array(path);

  _File.fromRawPath(Uint8List rawPath)
    : _rawPath = FileSystemEntity._toNullTerminatedUtf8Array(
        _checkNotNull(rawPath, "rawPath"),
      ),
      _path = FileSystemEntity._toStringFromUtf8Array(rawPath);

  String get path => _path;

  // WARNING:
  // Calling this function will increase the reference count on the native
  // namespace object. It should only be called to pass the pointer to the
  // IOService, which will decrement the reference count when it is finished
  // with it.
  static int _namespacePointer() => _Namespace._namespacePointer;

  static Future<Object?> _dispatchWithNamespace(int request, List data) {
    data[0] = _namespacePointer();
    return _IOService._dispatch(request, data);
  }

  Future<bool> exists() {
    return _dispatchWithNamespace(_IOService.fileExists, [null, _rawPath]).then(
      (response) {
        _checkForErrorResponse(response, "Cannot check existence", path);
        return response as bool;
      },
    );
  }

  external static _exists(_Namespace namespace, Uint8List rawPath);

  bool existsSync() {
    var result = _exists(_Namespace._namespace, _rawPath);
    throwIfError(result, "Cannot check existence of file", path);
    return result;
  }

  File get absolute => new File(_absolutePath);

  Future<File> create({bool recursive = false, bool exclusive = false}) {
    var result = recursive
        ? parent.create(recursive: true)
        : new Future.value(null);
    return result
        .then(
          (_) => _dispatchWithNamespace(_IOService.fileCreate, [
            null,
            _rawPath,
            exclusive,
          ]),
        )
        .then((response) {
          _checkForErrorResponse(response, "Cannot create file", path);
          return this;
        });
  }

  external static _create(
    _Namespace namespace,
    Uint8List rawPath,
    bool exclusive,
  );

  external static _createLink(
    _Namespace namespace,
    Uint8List rawPath,
    String target,
  );

  external static List<dynamic> _createPipe(_Namespace namespace);

  external static _linkTarget(_Namespace namespace, Uint8List rawPath);

  void createSync({bool recursive = false, bool exclusive = false}) {
    if (recursive) {
      parent.createSync(recursive: true);
    }
    var result = _create(_Namespace._namespace, _rawPath, exclusive);
    throwIfError(result, "Cannot create file", path);
  }

  Future<File> _delete({bool recursive = false}) {
    if (recursive) {
      return new Directory(path).delete(recursive: true).then((_) => this);
    }
    return _dispatchWithNamespace(_IOService.fileDelete, [null, _rawPath]).then(
      (response) {
        _checkForErrorResponse(response, "Cannot delete file", path);
        return this;
      },
    );
  }

  external static _deleteNative(_Namespace namespace, Uint8List rawPath);

  external static _deleteLinkNative(_Namespace namespace, Uint8List rawPath);

  void _deleteSync({bool recursive = false}) {
    if (recursive) {
      return new Directory.fromRawPath(_rawPath).deleteSync(recursive: true);
    }
    var result = _deleteNative(_Namespace._namespace, _rawPath);
    throwIfError(result, "Cannot delete file", path);
  }

  Future<File> rename(String newPath) {
    return _dispatchWithNamespace(_IOService.fileRename, [
      null,
      _rawPath,
      newPath,
    ]).then((response) {
      _checkForErrorResponse(
        response,
        "Cannot rename file to '$newPath'",
        path,
      );
      return new File(newPath);
    });
  }

  external static _rename(
    _Namespace namespace,
    Uint8List oldPath,
    String newPath,
  );

  external static _renameLink(
    _Namespace namespace,
    Uint8List oldPath,
    String newPath,
  );

  File renameSync(String newPath) {
    var result = _rename(_Namespace._namespace, _rawPath, newPath);
    throwIfError(result, "Cannot rename file to '$newPath'", path);
    return new File(newPath);
  }

  Future<File> copy(String newPath) {
    return _dispatchWithNamespace(_IOService.fileCopy, [
      null,
      _rawPath,
      newPath,
    ]).then((response) {
      _checkForErrorResponse(response, "Cannot copy file to '$newPath'", path);
      return new File(newPath);
    });
  }

  external static _copy(
    _Namespace namespace,
    Uint8List oldPath,
    String newPath,
  );

  File copySync(String newPath) {
    var result = _copy(_Namespace._namespace, _rawPath, newPath);
    throwIfError(result, "Cannot copy file to '$newPath'", path);
    return new File(newPath);
  }

  Future<RandomAccessFile> open({FileMode mode = FileMode.read}) {
    if (mode != FileMode.read &&
        mode != FileMode.write &&
        mode != FileMode.append &&
        mode != FileMode.writeOnly &&
        mode != FileMode.writeOnlyAppend) {
      return new Future.error(
        new ArgumentError('Invalid file mode for this operation'),
      );
    }
    return _dispatchWithNamespace(_IOService.fileOpen, [
      null,
      _rawPath,
      mode._mode,
    ]).then((response) {
      _checkForErrorResponse(response, "Cannot open file", path);
      return _RandomAccessFile(response as int, path);
    });
  }

  Future<int> length() {
    return _dispatchWithNamespace(_IOService.fileLengthFromPath, [
      null,
      _rawPath,
    ]).then((response) {
      _checkForErrorResponse(response, "Cannot retrieve length of file", path);
      return response as int;
    });
  }

  external static _lengthFromPath(_Namespace namespace, Uint8List rawPath);

  int lengthSync() {
    var result = _lengthFromPath(_Namespace._namespace, _rawPath);
    throwIfError(result, "Cannot retrieve length of file", path);
    return result;
  }

  Future<DateTime> lastAccessed() {
    return _dispatchWithNamespace(_IOService.fileLastAccessed, [
      null,
      _rawPath,
    ]).then((response) {
      _checkForErrorResponse(response, "Cannot retrieve access time", path);
      return DateTime.fromMillisecondsSinceEpoch(response as int);
    });
  }

  external static _lastAccessed(_Namespace namespace, Uint8List rawPath);

  DateTime lastAccessedSync() {
    var ms = _lastAccessed(_Namespace._namespace, _rawPath);
    throwIfError(ms, "Cannot retrieve access time", path);
    return new DateTime.fromMillisecondsSinceEpoch(ms);
  }

  Future setLastAccessed(DateTime time) {
    int millis = time.millisecondsSinceEpoch;
    return _dispatchWithNamespace(_IOService.fileSetLastAccessed, [
      null,
      _rawPath,
      millis,
    ]).then((response) {
      _checkForErrorResponse(response, "Cannot set access time", path);
      return null;
    });
  }

  external static _setLastAccessed(
    _Namespace namespace,
    Uint8List rawPath,
    int millis,
  );

  void setLastAccessedSync(DateTime time) {
    int millis = time.millisecondsSinceEpoch;
    var result = _setLastAccessed(_Namespace._namespace, _rawPath, millis);
    if (result is OSError) {
      throw new FileSystemException(
        "Failed to set file access time",
        path,
        result,
      );
    }
  }

  Future<DateTime> lastModified() {
    return _dispatchWithNamespace(_IOService.fileLastModified, [
      null,
      _rawPath,
    ]).then((response) {
      _checkForErrorResponse(
        response,
        "Cannot retrieve modification time",
        path,
      );
      return DateTime.fromMillisecondsSinceEpoch(response as int);
    });
  }

  external static _lastModified(_Namespace namespace, Uint8List rawPath);

  DateTime lastModifiedSync() {
    var ms = _lastModified(_Namespace._namespace, _rawPath);
    throwIfError(ms, "Cannot retrieve modification time", path);
    return new DateTime.fromMillisecondsSinceEpoch(ms);
  }

  Future setLastModified(DateTime time) {
    int millis = time.millisecondsSinceEpoch;
    return _dispatchWithNamespace(_IOService.fileSetLastModified, [
      null,
      _rawPath,
      millis,
    ]).then((response) {
      _checkForErrorResponse(response, "Cannot set modification time", path);
      return null;
    });
  }

  external static _setLastModified(
    _Namespace namespace,
    Uint8List rawPath,
    int millis,
  );

  void setLastModifiedSync(DateTime time) {
    int millis = time.millisecondsSinceEpoch;
    var result = _setLastModified(_Namespace._namespace, _rawPath, millis);
    if (result is OSError) {
      throw new FileSystemException(
        "Failed to set file modification time",
        path,
        result,
      );
    }
  }

  external static _open(_Namespace namespace, Uint8List rawPath, int mode);

  RandomAccessFile openSync({FileMode mode = FileMode.read}) {
    if (mode != FileMode.read &&
        mode != FileMode.write &&
        mode != FileMode.append &&
        mode != FileMode.writeOnly &&
        mode != FileMode.writeOnlyAppend) {
      throw new ArgumentError('Invalid file mode for this operation');
    }
    var id = _open(_Namespace._namespace, _rawPath, mode._mode);
    throwIfError(id, "Cannot open file", path);
    return new _RandomAccessFile(id, _path);
  }

  external static int _openStdio(int fd);

  static RandomAccessFile _openStdioSync(int fd) {
    var id = _openStdio(fd);
    if (id == 0) {
      throw new FileSystemException("Cannot open stdio file for: $fd");
    }
    return new _RandomAccessFile(id, "");
  }

  Stream<List<int>> openRead([int? start, int? end]) {
    return new _FileStream(path, start, end);
  }

  IOSink openWrite({FileMode mode = FileMode.write, Encoding encoding = utf8}) {
    if (mode != FileMode.write &&
        mode != FileMode.append &&
        mode != FileMode.writeOnly &&
        mode != FileMode.writeOnlyAppend) {
      throw new ArgumentError('Invalid file mode for this operation');
    }
    var consumer = new _FileStreamConsumer(this, mode);
    return new IOSink(consumer, encoding: encoding);
  }

  Future<Uint8List> readAsBytes() {
    Future<Uint8List> readUnsized(RandomAccessFile file) {
      var builder = new BytesBuilder(copy: false);
      var completer = new Completer<Uint8List>();
      void read() {
        file.read(_blockSize).then((data) {
          if (data.length > 0) {
            builder.add(data);
            read();
          } else {
            completer.complete(builder.takeBytes());
          }
        }, onError: completer.completeError);
      }

      read();
      return completer.future;
    }

    Future<Uint8List> readSized(RandomAccessFile file, int length) {
      var data = Uint8List(length);
      var offset = 0;
      var completer = new Completer<Uint8List>();
      void read() {
        file.readInto(data, offset, min(offset + _maxReadSize, length)).then((
          readSize,
        ) {
          if (readSize > 0) {
            offset += readSize;
            read();
          } else {
            assert(readSize == 0);
            if (offset < length) {
              data = Uint8List.sublistView(data, 0, offset);
            }
            completer.complete(data);
          }
        }, onError: completer.completeError);
      }

      read();
      return completer.future;
    }

    return open().then((file) {
      return file
          .length()
          .then((length) {
            if (length == 0) {
              // May be character device, try to read it in chunks.
              return readUnsized(file);
            }
            return readSized(file, length);
          })
          .whenComplete(file.close);
    });
  }

  Uint8List readAsBytesSync() {
    var opened = openSync();
    try {
      Uint8List data;
      var length = opened.lengthSync();
      if (length == 0) {
        // May be character device, try to read it in chunks.
        var builder = new BytesBuilder(copy: false);
        do {
          data = opened.readSync(_blockSize);
          if (data.length > 0) {
            builder.add(data);
          }
        } while (data.length > 0);
        data = builder.takeBytes();
      } else {
        data = Uint8List(length);
        var offset = 0;

        while (offset < length) {
          final readSize = opened.readIntoSync(
            data,
            offset,
            min(offset + _maxReadSize, length),
          );
          if (readSize == 0) {
            break;
          }
          offset += readSize;
        }

        if (offset < length) {
          data = Uint8List.view(data.buffer, 0, offset);
        }
      }
      return data;
    } finally {
      opened.closeSync();
    }
  }

  String _tryDecode(List<int> bytes, Encoding encoding) {
    try {
      return encoding.decode(bytes);
    } catch (_) {
      throw new FileSystemException(
        "Failed to decode data using encoding '${encoding.name}'",
        path,
      );
    }
  }

  Future<String> readAsString({Encoding encoding = utf8}) async =>
      _tryDecode(await readAsBytes(), encoding);

  String readAsStringSync({Encoding encoding = utf8}) =>
      _tryDecode(readAsBytesSync(), encoding);

  Future<List<String>> readAsLines({Encoding encoding = utf8}) =>
      readAsString(encoding: encoding).then(const LineSplitter().convert);

  List<String> readAsLinesSync({Encoding encoding = utf8}) =>
      const LineSplitter().convert(readAsStringSync(encoding: encoding));

  Future<File> writeAsBytes(
    List<int> bytes, {
    FileMode mode = FileMode.write,
    bool flush = false,
  }) {
    return open(mode: mode).then((file) {
      return file
          .writeFrom(bytes, 0, bytes.length)
          .then<File>((_) {
            if (flush) return file.flush().then((_) => this);
            return this;
          })
          .whenComplete(file.close);
    });
  }

  void writeAsBytesSync(
    List<int> bytes, {
    FileMode mode = FileMode.write,
    bool flush = false,
  }) {
    RandomAccessFile opened = openSync(mode: mode);
    try {
      opened.writeFromSync(bytes, 0, bytes.length);
      if (flush) opened.flushSync();
    } finally {
      opened.closeSync();
    }
  }

  Future<File> writeAsString(
    String contents, {
    FileMode mode = FileMode.write,
    Encoding encoding = utf8,
    bool flush = false,
  }) {
    try {
      return writeAsBytes(encoding.encode(contents), mode: mode, flush: flush);
    } catch (e) {
      return new Future.error(e);
    }
  }

  void writeAsStringSync(
    String contents, {
    FileMode mode = FileMode.write,
    Encoding encoding = utf8,
    bool flush = false,
  }) {
    writeAsBytesSync(encoding.encode(contents), mode: mode, flush: flush);
  }

  String toString() => "File: '$path'";

  static throwIfError(Object result, String msg, String path) {
    if (result is OSError) {
      throw FileSystemException._fromOSError(result, msg, path);
    }
  }

  // TODO(40614): Remove once non-nullability is sound.
  static T _checkNotNull<T>(T t, String name) {
    ArgumentError.checkNotNull(t, name);
    return t;
  }
}

abstract class _RandomAccessFileOps {
  external factory _RandomAccessFileOps._(int pointer);

  int _getPointer();
  int get fd;
  int close();
  readByte();
  read(int bytes);
  readInto(List<int> buffer, int start, int? end);
  writeByte(int value);
  writeFrom(List<int> buffer, int start, int? end);
  position();
  setPosition(int position);
  truncate(int length);
  length();
  flush();
  lock(int lock, int start, int end);
}

@pragma("vm:entry-point")
class _RandomAccessFile implements RandomAccessFile {
  static bool _connectedResourceHandler = false;

  final String path;

  bool _asyncDispatched = false;

  late _FileResourceInfo _resourceInfo;
  _RandomAccessFileOps _ops;

  @pragma("vm:entry-point")
  _RandomAccessFile(int pointer, this.path)
    : _ops = new _RandomAccessFileOps._(pointer) {
    _resourceInfo = new _FileResourceInfo(this);
    _maybeConnectHandler();
  }

  void _maybePerformCleanup() {
    if (closed) {
      _FileResourceInfo.fileClosed(_resourceInfo);
    }
  }

  _maybeConnectHandler() {
    if (!const bool.fromEnvironment("dart.vm.product") &&
        !_connectedResourceHandler) {
      // TODO(ricow): We probably need to set these in some initialization code.
      // We need to make sure that these are always available from the
      // observatory even if no files (or sockets for the socket ones) are
      // open.
      registerExtension(
        'ext.dart.io.getOpenFiles',
        _FileResourceInfo.getOpenFiles,
      );
      registerExtension(
        'ext.dart.io.getOpenFileById',
        _FileResourceInfo.getOpenFileInfoMapByID,
      );
      _connectedResourceHandler = true;
    }
  }

  Future<void> close() {
    return _dispatch(_IOService.fileClose, [null], markClosed: true).then((
      result,
    ) {
      if (result == -1) {
        throw new FileSystemException("Cannot close file", path);
      }
      closed = closed || (result == 0);
      _maybePerformCleanup();
    });
  }

  void closeSync() {
    _checkAvailable();
    var id = _ops.close();
    if (id == -1) {
      throw new FileSystemException("Cannot close file", path);
    }
    closed = closed || (id == 0);
    _maybePerformCleanup();
  }

  Future<int> readByte() {
    return _dispatch(_IOService.fileReadByte, [null]).then((response) {
      _checkForErrorResponse(response, "readByte failed", path);
      _resourceInfo.addRead(1);
      return response as int;
    });
  }

  int readByteSync() {
    _checkAvailable();
    var result = _ops.readByte();
    if (result is OSError) {
      throw new FileSystemException("readByte failed", path, result);
    }
    _resourceInfo.addRead(1);
    return result;
  }

  Future<Uint8List> read(int bytes) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(bytes, "bytes");
    return _dispatch(_IOService.fileRead, [null, bytes]).then((response) {
      _checkForErrorResponse(response, "read failed", path);
      var result = (response as List<Object?>)[1] as Uint8List;
      _resourceInfo.addRead(result.length);
      return result;
    });
  }

  Uint8List readSync(int bytes) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(bytes, "bytes");
    _checkAvailable();
    var result = _ops.read(bytes);
    if (result is! Uint8List) {
      throw new FileSystemException("readSync failed", path, result as OSError);
    }
    _resourceInfo.addRead(result.length);
    return result;
  }

  Future<int> readInto(List<int> buffer, [int start = 0, int? end]) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(buffer, "buffer");
    end = RangeError.checkValidRange(start, end, buffer.length);
    if (end == start) {
      return new Future.value(0);
    }
    int length = end - start;
    return _dispatch(_IOService.fileReadInto, [null, length]).then((response) {
      _checkForErrorResponse(response, "readInto failed", path);
      var responseList = response as List<Object?>;
      var read = responseList[1] as int;
      var data = responseList[2] as List<int>;
      buffer.setRange(start, start + read, data);
      _resourceInfo.addRead(read);
      return read;
    });
  }

  int readIntoSync(List<int> buffer, [int start = 0, int? end]) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(buffer, "buffer");
    _checkAvailable();
    end = RangeError.checkValidRange(start, end, buffer.length);
    if (end == start) {
      return 0;
    }
    var result = _ops.readInto(buffer, start, end);
    if (result is OSError) {
      throw new FileSystemException("readInto failed", path, result);
    }
    _resourceInfo.addRead(result);
    return result;
  }

  Future<RandomAccessFile> writeByte(int value) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(value, "value");
    return _dispatch(_IOService.fileWriteByte, [null, value]).then((response) {
      _checkForErrorResponse(response, "writeByte failed", path);
      _resourceInfo.addWrite(1);
      return this;
    });
  }

  int writeByteSync(int value) {
    _checkAvailable();
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(value, "value");
    var result = _ops.writeByte(value);
    if (result is OSError) {
      throw new FileSystemException("writeByte failed", path, result);
    }
    _resourceInfo.addWrite(1);
    return result;
  }

  Future<RandomAccessFile> writeFrom(
    List<int> buffer, [
    int start = 0,
    int? end,
  ]) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(buffer, "buffer");
    ArgumentError.checkNotNull(start, "start");
    end = RangeError.checkValidRange(start, end, buffer.length);
    if (end == start) {
      return new Future.value(this);
    }
    _BufferAndStart result;
    try {
      result = _ensureFastAndSerializableByteData(buffer, start, end);
    } catch (e) {
      return new Future.error(e);
    }

    List request = new List<dynamic>.filled(4, null);
    request[0] = null;
    request[1] = result.buffer;
    request[2] = result.start;
    request[3] = end - (start - result.start);
    return _dispatch(_IOService.fileWriteFrom, request).then((response) {
      _checkForErrorResponse(response, "writeFrom failed", path);
      _resourceInfo.addWrite(end! - (start - result.start));
      return this;
    });
  }

  void writeFromSync(List<int> buffer, [int start = 0, int? end]) {
    _checkAvailable();
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(buffer, "buffer");
    ArgumentError.checkNotNull(start, "start");
    end = RangeError.checkValidRange(start, end, buffer.length);
    if (end == start) {
      return;
    }
    _BufferAndStart bufferAndStart = _ensureFastAndSerializableByteData(
      buffer,
      start,
      end,
    );
    var result = _ops.writeFrom(
      bufferAndStart.buffer,
      bufferAndStart.start,
      end - (start - bufferAndStart.start),
    );
    if (result is OSError) {
      throw new FileSystemException("writeFrom failed", path, result);
    }
    _resourceInfo.addWrite(end - (start - bufferAndStart.start));
  }

  Future<RandomAccessFile> writeString(
    String string, {
    Encoding encoding = utf8,
  }) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(encoding, "encoding");
    var data = encoding.encode(string);
    return writeFrom(data, 0, data.length);
  }

  void writeStringSync(String string, {Encoding encoding = utf8}) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(encoding, "encoding");
    var data = encoding.encode(string);
    writeFromSync(data, 0, data.length);
  }

  Future<int> position() {
    return _dispatch(_IOService.filePosition, [null]).then((response) {
      _checkForErrorResponse(response, "position failed", path);
      return response as int;
    });
  }

  int positionSync() {
    _checkAvailable();
    var result = _ops.position();
    if (result is OSError) {
      throw new FileSystemException("position failed", path, result);
    }
    return result;
  }

  Future<RandomAccessFile> setPosition(int position) {
    return _dispatch(_IOService.fileSetPosition, [null, position]).then((
      response,
    ) {
      _checkForErrorResponse(response, "setPosition failed", path);
      return this;
    });
  }

  void setPositionSync(int position) {
    _checkAvailable();
    var result = _ops.setPosition(position);
    if (result is OSError) {
      throw new FileSystemException("setPosition failed", path, result);
    }
  }

  Future<RandomAccessFile> truncate(int length) {
    return _dispatch(_IOService.fileTruncate, [null, length]).then((response) {
      _checkForErrorResponse(response, "truncate failed", path);
      return this;
    });
  }

  void truncateSync(int length) {
    _checkAvailable();
    var result = _ops.truncate(length);
    if (result is OSError) {
      throw new FileSystemException("truncate failed", path, result);
    }
  }

  Future<int> length() {
    return _dispatch(_IOService.fileLength, [null]).then((response) {
      _checkForErrorResponse(response, "length failed", path);
      return response as int;
    });
  }

  int lengthSync() {
    _checkAvailable();
    var result = _ops.length();
    if (result is OSError) {
      throw new FileSystemException("length failed", path, result);
    }
    return result;
  }

  Future<RandomAccessFile> flush() {
    return _dispatch(_IOService.fileFlush, [null]).then((response) {
      _checkForErrorResponse(response, "flush failed", path);
      return this;
    });
  }

  void flushSync() {
    _checkAvailable();
    var result = _ops.flush();
    if (result is OSError) {
      throw new FileSystemException("flush failed", path, result);
    }
  }

  static const int lockUnlock = 0;
  // static const int lockShared = 1;
  // static const int lockExclusive = 2;
  // static const int lockBlockingShared = 3;
  // static const int lockBlockingExclusive = 4;

  int _fileLockValue(FileLock fl) => fl._type;

  Future<RandomAccessFile> lock([
    FileLock mode = FileLock.exclusive,
    int start = 0,
    int end = -1,
  ]) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(mode, "mode");
    ArgumentError.checkNotNull(start, "start");
    ArgumentError.checkNotNull(end, "end");
    if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
      throw new ArgumentError();
    }
    int lock = _fileLockValue(mode);
    return _dispatch(_IOService.fileLock, [null, lock, start, end]).then((
      response,
    ) {
      _checkForErrorResponse(response, 'lock failed', path);
      return this;
    });
  }

  Future<RandomAccessFile> unlock([int start = 0, int end = -1]) {
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(start, "start");
    ArgumentError.checkNotNull(end, "end");
    if (start == end) {
      throw new ArgumentError();
    }
    return _dispatch(_IOService.fileLock, [null, lockUnlock, start, end]).then((
      response,
    ) {
      _checkForErrorResponse(response, 'unlock failed', path);
      return this;
    });
  }

  void lockSync([
    FileLock mode = FileLock.exclusive,
    int start = 0,
    int end = -1,
  ]) {
    _checkAvailable();
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(mode, "mode");
    ArgumentError.checkNotNull(start, "start");
    ArgumentError.checkNotNull(end, "end");
    if ((start < 0) || (end < -1) || ((end != -1) && (start >= end))) {
      throw new ArgumentError();
    }
    int lock = _fileLockValue(mode);
    var result = _ops.lock(lock, start, end);
    if (result is OSError) {
      throw new FileSystemException('lock failed', path, result);
    }
  }

  void unlockSync([int start = 0, int end = -1]) {
    _checkAvailable();
    // TODO(40614): Remove once non-nullability is sound.
    ArgumentError.checkNotNull(start, "start");
    ArgumentError.checkNotNull(end, "end");
    if (start == end) {
      throw new ArgumentError();
    }
    var result = _ops.lock(lockUnlock, start, end);
    if (result is OSError) {
      throw new FileSystemException('unlock failed', path, result);
    }
  }

  bool closed = false;

  int get fd => _ops.fd;

  // WARNING:
  // Calling this function will increase the reference count on the native
  // object that implements the file operations. It should only be called to
  // pass the pointer to the IO Service, which will decrement the reference
  // count when it is finished with it.
  int _pointer() => _ops._getPointer();

  Future<Object?> _dispatch(int request, List data, {bool markClosed = false}) {
    if (closed) {
      return new Future.error(new FileSystemException("File closed", path));
    }
    if (_asyncDispatched) {
      var msg = "An async operation is currently pending";
      return new Future.error(new FileSystemException(msg, path));
    }
    if (markClosed) {
      // Set closed to true to ensure that no more async requests can be issued
      // for this file.
      closed = true;
    }
    _asyncDispatched = true;
    data[0] = _pointer();
    return _IOService._dispatch(request, data).whenComplete(() {
      _asyncDispatched = false;
    });
  }

  void _checkAvailable() {
    if (_asyncDispatched) {
      throw new FileSystemException(
        "An async operation is currently pending",
        path,
      );
    }
    if (closed) {
      throw new FileSystemException("File closed", path);
    }
  }
}

class _ReadPipe extends _FileStream implements ReadPipe {
  _ReadPipe(RandomAccessFile file) : super.forRandomAccessFile(file);
}

class _WritePipe extends _IOSinkImpl implements WritePipe {
  RandomAccessFile _file;
  _WritePipe(file)
    : this._file = file,
      super(_FileStreamConsumer.fromRandomAccessFile(file), utf8);
}

class _Pipe implements Pipe {
  final ReadPipe _readPipe;
  final WritePipe _writePipe;

  ReadPipe get read => _readPipe;
  WritePipe get write => _writePipe;

  _Pipe(this._readPipe, this._writePipe);

  static Future<_Pipe> create() {
    final completer = Completer<_Pipe>.sync();

    _File._dispatchWithNamespace(_IOService.fileCreatePipe, [null]).then((
      response,
    ) {
      final filePointers = (response as List).cast<int>();
      completer.complete(
        _Pipe(
          _ReadPipe(_RandomAccessFile(filePointers[0], '')),
          _WritePipe(_RandomAccessFile(filePointers[1], '')),
        ),
      );
    });
    return completer.future;
  }

  factory _Pipe.createSync() {
    final filePointers = _File._createPipe(_Namespace._namespace);
    return _Pipe(
      _ReadPipe(_RandomAccessFile(filePointers[0] as int, '')),
      _WritePipe(_RandomAccessFile(filePointers[1] as int, '')),
    );
  }
}
