| // Copyright (c) 2016, 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. |
| |
| library front_end.memory_file_system; |
| |
| import 'dart:convert'; |
| import 'dart:typed_data'; |
| |
| import 'file_system.dart'; |
| |
| /// Concrete implementation of [FileSystem] which performs its operations on an |
| /// in-memory virtual file system. |
| /// |
| /// Not intended to be implemented or extended by clients. |
| class MemoryFileSystem implements FileSystem { |
| final Map<Uri, Uint8List> _files = {}; |
| final Set<Uri> _directories = new Set<Uri>(); |
| |
| /// The "current directory" in the in-memory virtual file system. |
| /// |
| /// This is used to convert relative URIs to absolute URIs. |
| /// |
| /// Always ends in a trailing '/'. |
| Uri currentDirectory; |
| |
| MemoryFileSystem(Uri currentDirectory) |
| : currentDirectory = _addTrailingSlash(currentDirectory) { |
| _directories.add(currentDirectory); |
| } |
| |
| @override |
| MemoryFileSystemEntity entityForUri(Uri uri) { |
| return new MemoryFileSystemEntity._( |
| this, currentDirectory.resolveUri(uri).normalizePath()); |
| } |
| |
| String get debugString { |
| StringBuffer sb = new StringBuffer(); |
| _files.forEach((uri, _) => sb.write("- $uri\n")); |
| _directories.forEach((uri) => sb.write("- $uri\n")); |
| return '$sb'; |
| } |
| |
| static Uri _addTrailingSlash(Uri uri) { |
| if (!uri.path.endsWith('/')) { |
| uri = uri.replace(path: uri.path + '/'); |
| } |
| return uri; |
| } |
| } |
| |
| /// Concrete implementation of [FileSystemEntity] for use by |
| /// [MemoryFileSystem]. |
| class MemoryFileSystemEntity implements FileSystemEntity { |
| final MemoryFileSystem _fileSystem; |
| |
| @override |
| final Uri uri; |
| |
| MemoryFileSystemEntity._(this._fileSystem, this.uri); |
| |
| @override |
| int get hashCode => uri.hashCode; |
| |
| @override |
| bool operator ==(Object other) => |
| other is MemoryFileSystemEntity && |
| other.uri == uri && |
| identical(other._fileSystem, _fileSystem); |
| |
| /// Create a directory for this file system entry. |
| /// |
| /// If the entry is an existing file, this is an error. |
| void createDirectory() { |
| if (_fileSystem._files[uri] != null) { |
| throw new FileSystemException(uri, 'Entry $uri is a file.'); |
| } |
| _fileSystem._directories.add(uri); |
| } |
| |
| @override |
| Future<bool> exists() async { |
| return _fileSystem._files[uri] != null || |
| _fileSystem._directories.contains(uri); |
| } |
| |
| @override |
| Future<List<int>> readAsBytes() async { |
| Uint8List? contents = _fileSystem._files[uri]; |
| if (contents == null) { |
| throw new FileSystemException(uri, 'File $uri does not exist.'); |
| } |
| return contents; |
| } |
| |
| @override |
| Future<String> readAsString() async { |
| List<int> bytes = await readAsBytes(); |
| try { |
| return utf8.decode(bytes); |
| } on FormatException catch (e) { |
| throw new FileSystemException(uri, e.message); |
| } |
| } |
| |
| /// Writes the given raw bytes to this file system entity. |
| /// |
| /// If no file exists, one is created. If a file exists already, it is |
| /// overwritten. |
| void writeAsBytesSync(List<int> bytes) { |
| if (bytes is Uint8List) { |
| _update(uri, bytes); |
| } else { |
| _update(uri, new Uint8List.fromList(bytes)); |
| } |
| } |
| |
| /// Writes the given string to this file system entity. |
| /// |
| /// The string is encoded as UTF-8. |
| /// |
| /// If no file exists, one is created. If a file exists already, it is |
| /// overwritten. |
| void writeAsStringSync(String s) { |
| // Note: the return type of utf8.encode is List<int>, but in practice it |
| // always returns Uint8List. We rely on that for efficiency, so that we |
| // don't have to make an extra copy. |
| _update(uri, utf8.encode(s) as Uint8List); |
| } |
| |
| void _update(Uri uri, Uint8List data) { |
| if (_fileSystem._directories.contains(uri)) { |
| throw new FileSystemException(uri, 'Entry $uri is a directory.'); |
| } |
| _fileSystem._files[uri] = data; |
| } |
| } |