// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:_mojo_services/mojo/files/types.mojom.dart' as types;

//
// Implementation of Directory, File, and RandomAccessFile for Mojo.
//

// Helper to convert from mojo:files error to OSError.
OSError _OSErrorFromError(types.Error error) {
  assert(error != null);
  return new OSError(error.toString(), error.toJson());
}

// All paths in mojo:files are relative to the root directory. This helper
// strips away any leading slashes.
String _ensurePathIsRelative(String path) {
  while (path.startsWith('/')) {
    // Trim off the leading '/'.
    path = path.substring(1);
  }
  return path;
}

// The mojo implementation of dart:io does not support any synchronous
// file operations. This helper throws an unsupported error.
dynamic _onSyncOperation() {
  throw new UnsupportedError(
      "Synchronous operations are not supported by this embedder");
}

// Convert from mojo:files Timespec to DateTime.
DateTime _dateTimeFromTimespec(types.Timespec ts) {
  if (ts == null) {
    // Dawn of time.
    return new DateTime.fromMillisecondsSinceEpoch(0);
  }
  int microseconds = ts.seconds * Duration.MICROSECONDS_PER_SECOND;
  microseconds += ts.nanoseconds ~/ 1000;
  return new DateTime.fromMicrosecondsSinceEpoch(microseconds);
}

// Convert from mojo:files FileType to FileSystemEntityType.
FileSystemEntityType _fileSystemEntityTypeFromFileType(types.FileType ft) {
  if (ft == types.FileType.unknown) {
    return FileSystemEntityType.NOT_FOUND;
  } else if (ft == types.FileType.regularFile) {
    return FileSystemEntityType.FILE;
  } else if (ft == types.FileType.directory) {
    return FileSystemEntityType.DIRECTORY;
  }
  throw new UnimplementedError();
  return FileSystemEntityType.NOT_FOUND;
}

// Convert from dart:io FileMode to open flags.
int _openFlagsFromFileMode(FileMode fileMode) {
  int flags = 0;
  switch (fileMode) {
    case FileMode.READ:
      flags = types.kOpenFlagRead;
      break;
    case FileMode.WRITE:
      flags = types.kOpenFlagRead |
              types.kOpenFlagWrite |
              types.kOpenFlagTruncate |
              types.kOpenFlagCreate;
      break;
    case FileMode.APPEND:
      flags = types.kOpenFlagRead |
              types.kOpenFlagWrite |
              types.kOpenFlagAppend |
              types.kOpenFlagCreate;
      break;
    case FileMode.WRITE_ONLY:
      flags = types.kOpenFlagWrite |
              types.kOpenFlagTruncate |
              types.kOpenFlagCreate;
      break;
    case FileMode.WRITE_ONLY_APPEND:
      flags = types.kOpenFlagWrite |
              types.kOpenFlagAppend |
              types.kOpenFlagCreate;
      break;
    default:
      throw new UnimplementedError();
  }
  return flags;
}

patch class _Directory {
  // We start at the root of the file system.
  static String _currentDirectoryPath = '/';

  /* patch */ Future<Directory> create({bool recursive: false}) async {
    if (recursive) {
      return exists().then((exists) {
        if (exists) return this;
        if (path != parent.path) {
          return parent.create(recursive: true).then((_) {
            return create();
          });
        } else {
          return create();
        }
      });
    }
    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags =
        types.kOpenFlagRead | types.kOpenFlagWrite | types.kOpenFlagCreate;
    var response =
        await rootDirectory.responseOrError(
            rootDirectory.ptr.openDirectory(_ensurePathIsRelative(path),
                                            null,
                                            flags));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    return this;
  }

  /* patch */ void createSync({bool recursive: false}) => _onSyncOperation();

  /* patch */ Future<Directory> createTemp([String prefix]) async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    // Create directory and fail if it already exists.
    int flags = types.kOpenFlagRead | types.kOpenFlagWrite |
                types.kOpenFlagCreate | types.kOpenFlagExclusive;
    String tempPath = '$path/$prefix';
    while (true) {
      var response =
          await rootDirectory.responseOrError(
              rootDirectory.ptr.openDirectory(tempPath, null, flags));
      if (response.error == types.Error.ok) {
        // Success.
        break;
      }
      // Alter the path and try again.
      // TODO(johnmccutchan): Append a randomly generated character.
      tempPath = tempPath + 'a';
    }
    return new Directory(tempPath);
  }

  /* patch */ Directory createTempSync([String prefix]) => _onSyncOperation();

  /* patch */ Future<bool> exists() async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags = types.kOpenFlagRead | types.kOpenFlagWrite;
    var response =
        await await rootDirectory.responseOrError(
            rootDirectory.ptr.openDirectory(_ensurePathIsRelative(path),
                                            null,
                                            flags));
    // If we can open it, it exists.
    return response.error == types.Error.ok;
  }

  /* patch */ bool existsSync() => _onSyncOperation();

  /* patch */ Stream<FileSystemEntity> list({bool recursive: false,
                                            bool followLinks: true}) {
    _DirectoryLister directoryLister = new _DirectoryLister(path, recursive);
    StreamController streamController = new StreamController();
    directoryLister.list(streamController);
    return streamController.stream;
  }

  /* patch */ List listSync({bool recursive: false,
                             bool followLinks: true}) {
    return _onSyncOperation();
  }

  /* patch */ Future<FileStat> stat() {
    return FileStat.stat(path);
  }

  /* patch */ FileStat statSync() => _onSyncOperation();

  /* patch */ Future<Directory> rename(String newPath) async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    var response = await rootDirectory.responseOrError(
        rootDirectory.ptr.rename(_ensurePathIsRelative(path),
                                 _ensurePathIsRelative(newPath)));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    return new Directory(newPath);
  }

  /* patch */ Directory renameSync(String newPath) => _onSyncOperation();

  /* patch */ static _current() {
    return _currentDirectoryPath;
  }

  /* patch */ static _setCurrent(path) {
    _currentDirectoryPath = path;
  }

  /* patch */ static _createTemp(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static String _systemTemp() {
    return 'tmp';
  }

  /* patch */ static _exists(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _create(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _deleteNative(String path, bool recursive) {
    throw new UnimplementedError();
  }

  /* patch */ static _rename(String path, String newPath) {
    throw new UnimplementedError();
  }

  /* patch */ static List _list(String path, bool recursive, bool followLinks) {
    throw new UnimplementedError();
  }
}


class _DirectoryLister {
  final String _path;
  final bool _recursive;
  final List<String> _directoriesToList = new List<String>();

  _DirectoryLister(this._path, this._recursive);

  list(StreamController streamController) async {
    _directoriesToList.add(_path);

    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags = types.kOpenFlagRead | types.kOpenFlagWrite;

    while (_directoriesToList.length > 0) {
      // Remove head.
      String path = _directoriesToList.removeAt(0);
      // Open directory.
      DirectoryProxy directory = new DirectoryProxy.unbound();
      var response =
          await rootDirectory.responseOrError(
              rootDirectory.ptr.openDirectory(_ensurePathIsRelative(path),
                                              directory,
                                              flags));
      if (response.error != types.Error.ok) {
        // Skip if we can't open it.
        continue;
      }
      // Read contents.
      var readResponse = await directory.responseOrError(directory.ptr.read());
      // We are done with the directory now.
      directory.close(immediate: true);
      if (readResponse.error != types.Error.ok) {
        // Skip if we can't read it.
        continue;
      }
      List<types.DirectoryEntry> directoryContents =
          readResponse.directoryContents;
      for (types.DirectoryEntry entry in directoryContents) {
        String childPath = '$path/${entry.name}';
        if (entry.type == types.FileType.directory) {
          if (_recursive) {
            if ((entry.name != '.') && (entry.name != '..')) {
              _directoriesToList.add(childPath);
            }
          }
          streamController.add(new Directory(childPath));
        } else {
          streamController.add(new File(childPath));
        }
      }
    }
    streamController.close();
  }
}

patch class _File {
  /* patch */ Future<bool> exists() async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags = types.kOpenFlagRead;
    var response =
        await rootDirectory.responseOrError(
            rootDirectory.ptr.openFile(_ensurePathIsRelative(path),
                                       null,
                                       flags));
    // If we can open it, it exists.
    return response.error == types.Error.ok;
  }

  /* patch */ bool existsSync() => _onSyncOperation();

  /* patch */ FileStat statSync() => _onSyncOperation();

  /* patch */ Future<File> create({bool recursive: false}) async {
    if (recursive) {
      // Create any parent directories.
      await parent.create(recursive: true);
    }
    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags = types.kOpenFlagWrite | types.kOpenFlagCreate;
    var response =
        await rootDirectory.responseOrError(
            rootDirectory.ptr.openFile(_ensurePathIsRelative(path),
                                       null,
                                       flags));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    return this;
  }

  /* patch */ void createSync({bool recursive: false}) => _onSyncOperation();

  /* patch */ Future<File> rename(String newPath) async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    var response = await rootDirectory.responseOrError(
        rootDirectory.ptr.rename(_ensurePathIsRelative(path),
                                 _ensurePathIsRelative(newPath)));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    return new File(newPath);
  }

  /* patch */ File renameSync(String newPath) => _onSyncOperation();

  /* patch */ Future<File> copy(String newPath) async {
    File copyFile = new File(newPath);
    Stream<List<int>> input = openRead();
    IOSink output = copyFile.openWrite();
    // Copy contents.
    await output.addStream(input);
    // Close.
    await output.close();
    return copyFile;
  }

  /* patch */ File copySync(String newPath) => _onSyncOperation();

  /* patch */ Future<RandomAccessFile> open(
      {FileMode mode: FileMode.READ}) async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    FileProxy file = new FileProxy.unbound();
    var response = await rootDirectory.responseOrError(
        rootDirectory.ptr.openFile(_ensurePathIsRelative(path),
                                   file,
                                   _openFlagsFromFileMode(mode)));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    // We use the raw mojo handle as our fd.
    final int fd = file.impl.endpoint.handle.h;
    // Construct the RandomAccessFile using the original constructor.
    _RandomAccessFile raf = new _RandomAccessFile(fd, path);
    // Hook up our proxy.
    raf._proxy = file;
    return raf;
  }

  /* patch */ Future<int> length() async {
    FileStat fileStat = await FileStat.stat(path);
    return fileStat.size;
  }

  /* patch */ int lengthSync() => _onSyncOperation();

  /* patch */ Future<DateTime> lastModified() async {
    FileStat fileStat = await FileStat.stat(path);
    return fileStat.modified;
  }

  /* patch */ DateTime lastModifiedSync() => _onSyncOperation();

  /* patch */ RandomAccessFile openSync({FileMode mode: FileMode.READ}) {
    return _onSyncOperation();
  }

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

  /* patch */ IOSink openWrite({FileMode mode: FileMode.WRITE,
                                Encoding encoding: UTF8}) {
    if (mode != FileMode.WRITE &&
        mode != FileMode.APPEND &&
        mode != FileMode.WRITE_ONLY &&
        mode != FileMode.WRITE_ONLY_APPEND) {
      throw new ArgumentError('Invalid file mode for this operation');
    }
    var consumer = new _FileStreamConsumer(this, mode);
    return new IOSink(consumer, encoding: encoding);
  }

  /* patch */ Future<List<int>> readAsBytes() async {
    RandomAccessFile raf = await open();
    int length = await raf.length();
    var bytes = await raf.read(length);
    await raf.close();
    return bytes;
  }

  /* patch */ List<int> readAsBytesSync() => _onSyncOperation();

  /* patch */ String readAsStringSync({Encoding encoding: UTF8}) {
    return _onSyncOperation();
  }

  /* patch */ List<String> readAsLinesSync({Encoding encoding: UTF8}) {
    return _onSyncOperation();
  }

  /* patch */ Future<File> writeAsBytes(List<int> bytes,
                                        {FileMode mode: FileMode.WRITE,
                                         bool flush: false}) async {
    RandomAccessFile raf = await open(mode: mode);
    await raf.writeFrom(bytes, 0, bytes.length);
    await raf.close();
    return this;
  }

  /* patch */ void writeAsBytesSync(List<int> bytes,
                                    {FileMode mode: FileMode.WRITE,
                                     bool flush: false}) {
    _onSyncOperation();
  }

  /* patch */ void writeAsStringSync(String contents,
                                     {FileMode mode: FileMode.WRITE,
                                      Encoding encoding: UTF8,
                                      bool flush: false}) {
    _onSyncOperation();
  }

  /* patch */ static _exists(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _create(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _createLink(String path, String target) {
    throw new UnimplementedError();
  }

  /* patch */ static _linkTarget(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _deleteNative(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _deleteLinkNative(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _rename(String oldPath, String newPath) {
    throw new UnimplementedError();
  }

  /* patch */ static _renameLink(String oldPath, String newPath) {
    throw new UnimplementedError();
  }

  /* patch */ static _copy(String oldPath, String newPath) {
    throw new UnimplementedError();
  }

  /* patch */ static _lengthFromPath(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _lastModified(String path) {
    throw new UnimplementedError();
  }

  /* patch */ static _open(String path, int mode) {
    throw new UnimplementedError();
  }

  /* patch */ static int _openStdio(int fd) {
    throw new UnimplementedError();
  }
}

patch class FileStat {
  /* patch */ static FileStat statSync(String path) {
    return _onSyncOperation();
  }

  /* patch */ static Future<FileStat> stat(String path) async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags = types.kOpenFlagRead | types.kOpenFlagWrite;
    DirectoryProxy directory = new DirectoryProxy.unbound();
    var response =
        await await rootDirectory.responseOrError(
            rootDirectory.ptr.openDirectory(_ensurePathIsRelative(path),
                                            directory,
                                            flags));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    var statResponse = await directory.responseOrError(directory.ptr.stat());
    // We are done with the directory now.
    directory.close(immediate: true);
    if (statResponse.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    types.FileInformation fileInformation = statResponse.fileInformation;
    DateTime modified = _dateTimeFromTimespec(fileInformation.mtime);
    DateTime accessed = _dateTimeFromTimespec(fileInformation.atime);
    int size = fileInformation.size;
    const userReadWriteExecutableUnixMode = 0x1c0;
    FileSystemEntityType fset =
        _fileSystemEntityTypeFromFileType(fileInformation.type);
    return new FileStat._internal(modified,
                                  modified,
                                  accessed,
                                  fset,
                                  userReadWriteExecutableUnixMode,
                                  size);
  }

  /* patch */ static _statSync(String path) {
    _onSyncOperation();
  }
}


patch class FileSystemEntity {
  /* patch */ Future<String> resolveSymbolicLinks() {
    // TODO(johnmccutchan): Canonicalize path before returning.
    return path;
  }

  /* patch */ String resolveSymbolicLinksSync() {
    return _onSyncOperation();
  }

  /* patch */ Future<FileSystemEntity> delete({bool recursive: false}) async {
    DirectoryProxy rootDirectory = await _getRootDirectory();
    int flags = recursive ? types.kDeleteFlagRecursive : 0;
    var response = await rootDirectory.responseOrError(
        rootDirectory.ptr.delete(_ensurePathIsRelative(path), flags));
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
    return this;
  }

  /* patch */ void deleteSync({bool recursive: false}) {
    _onSyncOperation();
  }

  /* patch */ Stream<FileSystemEvent> watch({int events: FileSystemEvent.ALL,
                                             bool recursive: false}) {
    throw new UnsupportedError(
        "File system watch is not supported by this embedder");
  }

  /* patch */ static Future<bool> identical(String path1, String path2) {
    // TODO(johnmccutchan): Canonicalize paths before comparing.
    return path1 == path2;
  }

  /* patch */ static bool identicalSync(String path1, String path2) {
    return _onSyncOperation();
  }

  /* patch */ static Future<FileSystemEntityType> type(
      String path, {bool followLinks: true}) async {
    FileStat fs = await FileStat.stat(path);
    return fs.type;
  }

  /* patch */ static FileSystemEntityType typeSync(
      String path, {bool followLinks: true}) {
      return _onSyncOperation();
  }

  /* patch */ static _getType(String path, bool followLinks) {
    throw new UnimplementedError();
  }
  /* patch */ static _identical(String path1, String path2) {
    throw new UnimplementedError();
  }
  /* patch */ static _resolveSymbolicLinks(String path) {
    throw new UnimplementedError();
  }
}

patch class _Link {
}


patch class _RandomAccessFile {
  FileProxy _proxy;

  void _ensureProxy() {
    if (_proxy == null) {
      throw new StateError("_RandomAccessFile has a null proxy.");
    }
  }

  void _handleError(dynamic response) {
    if (response.error != types.Error.ok) {
      throw _OSErrorFromError(response.error);
    }
  }

  /* patch */ Future<RandomAccessFile> close() async {
    _ensureProxy();
    await _proxy.responseOrError(_proxy.ptr.close());
    await _proxy.close(immediate: true);
    _proxy = null;
    _id = 0;
    _maybePerformCleanup();
    return this;
  }

  /* patch */ void closeSync() {
    _onSyncOperation();
  }

  /* patch */ Future<int> readByte() async {
    _ensureProxy();
    var response = await _proxy.responseOrError(
        _proxy.ptr.read(1, 0, types.Whence.fromCurrent));
    _handleError(response);
    _resourceInfo.addRead(response.bytesRead.length);
    if (response.bytesRead.length == 0) {
      throw new FileSystemException("readByte failed.");
    }
    return response.bytesRead[0];
  }

  /* patch */ int readByteSync() {
    return _onSyncOperation();
  }

  /* patch */ Future<List<int>> read(int bytes) async {
    if (bytes is !int) {
      throw new ArgumentError(bytes);
    }
    _ensureProxy();
    var response = await _proxy.responseOrError(
        _proxy.ptr.read(bytes, 0, types.Whence.fromCurrent));
    _handleError(response);
    _resourceInfo.addRead(response.bytesRead.length);
    return response.bytesRead;
  }

  /* patch */ List<int> readSync(int bytes) {
    return _onSyncOperation();
  }

  /* patch */ Future<int> readInto(List<int> buffer,
                                   [int start = 0, int end]) async {
    if (buffer is !List ||
        (start != null && start is !int) ||
        (end != null && end is !int)) {
      throw new ArgumentError();
    }
    end = RangeError.checkValidRange(start, end, buffer.length);
    _ensureProxy();
    if (end == start) {
      return 0;
    }
    int length = end - start;
    var response = await _proxy.responseOrError(
        _proxy.ptr.read(length, 0, types.Whence.fromCurrent));
    _handleError(response);
    int read = response.bytesRead.length;
    _resourceInfo.addRead(read);
    buffer.setRange(start, start + read, response.bytesRead);
    return read;
  }

  /* patch */ int readIntoSync(List<int> buffer, [int start = 0, int end]) {
    return _onSyncOperation();
  }

  /* patch */ Future<RandomAccessFile> writeByte(int value) async {
    if (value is !int) {
      throw new ArgumentError(value);
    }
    _ensureProxy();
    var response = await _proxy.responseOrError(
        _proxy.ptr.write([value], 0, types.Whence.fromCurrent));
    _handleError(response);
    assert(response.numBytesWritten == 1);
    _resourceInfo.addWrite(response.numBytesWritten);
    return this;
  }

  /* patch */ int writeByteSync(int value) {
    return _onSyncOperation();
  }

  /* patch */ Future<RandomAccessFile> writeFrom(
      List<int> buffer, [int start = 0, int end]) async {
    if ((buffer is !List) ||
        (start != null && start is !int) ||
        (end != null && end is !int)) {
      throw new ArgumentError("Invalid arguments to writeFrom");
    }
    end = RangeError.checkValidRange(start, end, buffer.length);
    _ensureProxy();
    if (end == start) {
      return this;
    }
    _BufferAndStart result;
    final int length = end - start;
    result = _ensureFastAndSerializableByteData(buffer, start, end);
    if (result.start != 0) {
      // Slow path where we copy the contents of buffer into a new buffer
      // so that the data we want to write starts at the beginning of the
      // buffer.
      final buffer = new Uint8List(length);
      buffer.setRange(0, length, result.buffer, start);
      // Replace the buffer in result.
      result.buffer = buffer;
      result.start = 0;
    }
    assert(result.start == 0);
    var response = await _proxy.responseOrError(
        _proxy.ptr.write(result.buffer, 0, types.Whence.fromCurrent));
    _handleError(response);
    _resourceInfo.addWrite(response.numBytesWritten);
    return this;
  }

  /* patch */ void writeFromSync(List<int> buffer, [int start = 0, int end]) {
    _onSyncOperation();
  }

  /* patch */ void writeStringSync(String string, {Encoding encoding: UTF8}) {
    _onSyncOperation();
  }

  /* patch */ Future<int> position() async {
    _ensureProxy();
    var response = await _proxy.responseOrError(_proxy.ptr.tell());
    _handleError(response);
    return response.position;
  }

  /* patch */ int positionSync() {
    _onSyncOperation();
  }

  /* patch */ Future<RandomAccessFile> setPosition(int position) async {
    if (position is !int) {
      throw new ArgumentError(position);
    }
    _ensureProxy();
    var response = await _proxy.responseOrError(
        _proxy.ptr.seek(position, types.Whence.fromStart));
    _handleError(response);
    return this;
  }

  /* patch */ void setPositionSync(int position) {
    _onSyncOperation();
  }

  /* patch */ Future<RandomAccessFile> truncate(int length) async {
    if (length is !int) {
      throw new ArgumentError(length);
    }
    _ensureProxy();
    var response = await _proxy.responseOrError(_proxy.ptr.truncate(length));
    _handleError(response);
  }

  /* patch */ void truncateSync(int length) {
    _onSyncOperation();
  }

  /* patch */ Future<int> length() async {
    _ensureProxy();
    var response = await _proxy.responseOrError(_proxy.ptr.stat());
    _handleError(response);
    return response.fileInformation.size;
  }

  /* patch */ int lengthSync() {
    _onSyncOperation();
  }

  /* patch */ Future<RandomAccessFile> flush() {
    return this;
  }

  /* patch */ void flushSync() {
    _onSyncOperation();
  }

  /* patch */ Future<RandomAccessFile> lock(
      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) {
    throw new UnsupportedError(
        "File locking is not supported by this embedder");
  }

  /* patch */ Future<RandomAccessFile> unlock([int start = 0, int end]) {
    throw new UnsupportedError(
        "File locking is not supported by this embedder");
  }

  /* patch */ void lockSync(
      [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end]) {
    _onSyncOperation();
  }

  /* patch */ void unlockSync([int start = 0, int end]) {
    _onSyncOperation();
  }

  /* patch */ bool get closed => _id == 0;

  /* patch */ static int _close(int id) {
    throw new UnimplementedError();
  }

  /* patch */ static int _getFD(int id) {
    throw new UnimplementedError();
  }

  /* patch */ static _readByte(int id) {
    throw new UnimplementedError();
  }

  /* patch */ static _read(int id, int bytes) {
    throw new UnimplementedError();
  }

  /* patch */ static _readInto(int id, List<int> buffer, int start, int end) {
    throw new UnimplementedError();
  }

  /* patch */ static _writeByte(int id, int value) {
    throw new UnimplementedError();
  }

  /* patch */ static _writeFrom(int id, List<int> buffer, int start, int end) {
    throw new UnimplementedError();
  }

  /* patch */ static _position(int id) {
    throw new UnimplementedError();
  }

  /* patch */ static _setPosition(int id, int position) {
    throw new UnimplementedError();
  }

  /* patch */ static _truncate(int id, int length) {
    throw new UnimplementedError();
  }

  /* patch */ static _length(int id) {
    throw new UnimplementedError();
  }

  /* patch */ static _flush(int id) {
    throw new UnimplementedError();
  }

  /* patch */ static _lock(int id, int lock, int start, int end) {
    throw new UnimplementedError();
  }
}
