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

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

  // Information about the underlying file.
  String? _path;
  late 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;

  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;
      if (block.length < readBytes || (_end != null && _position == _end)) {
        _atEnd = true;
      }
      if (!_atEnd && !_controller.isPaused) {
        _readBlock();
      }
      _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;
    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 extends 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));

  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 _dispatchWithNamespace(int request, List data) {
    data[0] = _namespacePointer();
    return _IOService._dispatch(request, data);
  }

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

  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}) {
    var result =
        recursive ? parent.create(recursive: true) : new Future.value(null);
    return result
        .then((_) =>
            _dispatchWithNamespace(_IOService.fileCreate, [null, _rawPath]))
        .then((response) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "Cannot create file", path);
      }
      return this;
    });
  }

  external static _create(_Namespace namespace, Uint8List rawPath);

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

  external static _linkTarget(_Namespace namespace, Uint8List rawPath);

  void createSync({bool recursive: false}) {
    if (recursive) {
      parent.createSync(recursive: true);
    }
    var result = _create(_Namespace._namespace, _rawPath);
    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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(
            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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(
            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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "Cannot open file", path);
      }
      return new _RandomAccessFile(response, path);
    });
  }

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

  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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(
            response, "Cannot retrieve access time", path);
      }
      return new DateTime.fromMillisecondsSinceEpoch(response);
    });
  }

  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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(
            response, "Cannot retrieve modification time", path);
      }
      return new DateTime.fromMillisecondsSinceEpoch(response);
    });
  }

  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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(
            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> readDataChunked(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;
    }

    return open().then((file) {
      return file.length().then((length) {
        if (length == 0) {
          // May be character device, try to read it in chunks.
          return readDataChunked(file);
        }
        return file.read(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 = opened.readSync(length);
      }
      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}) {
    // TODO(dart:io): If the change in async semantics to run synchronously
    // until await lands, this is as efficient as
    // return _tryDecode(await readAsBytes(), encoding);
    var stack = StackTrace.current;
    return readAsBytes().then((bytes) {
      try {
        return _tryDecode(bytes, encoding);
      } catch (e) {
        return new Future.error(e, stack);
      }
    });
  }

  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 new FileSystemException(msg, path, result);
    }
  }

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

class _RandomAccessFile implements RandomAccessFile {
  static bool _connectedResourceHandler = false;

  final String path;

  bool _asyncDispatched = false;

  late _FileResourceInfo _resourceInfo;
  _RandomAccessFileOps _ops;

  _RandomAccessFile(int pointer, this.path)
      : _ops = new _RandomAccessFileOps(pointer) {
    _resourceInfo = new _FileResourceInfo(this);
    _maybeConnectHandler();
  }

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

  _maybeConnectHandler() {
    if (!_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.getFileByID', _FileResourceInfo.getFileInfoMapByID);
      _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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "readByte failed", path);
      }
      _resourceInfo.addRead(1);
      return response;
    });
  }

  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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "read failed", path);
      }
      _resourceInfo.addRead(response[1].length);
      Uint8List result = response[1];
      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 OSError) {
      throw new FileSystemException("readSync failed", path, result);
    }
    _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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "readInto failed", path);
      }
      int read = response[1];
      List<int> data = response[2];
      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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "position failed", path);
      }
      return response;
    });
  }

  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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(response, "length failed", path);
      }
      return response;
    });
  }

  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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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) {
      if (_isErrorResponse(response)) {
        throw _exceptionFromResponse(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;

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