blob: babbed31a50bb09743a0d8b37f810bd0fb0ddfcc [file] [log] [blame] [edit]
// Copyright (c) 2023, 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.
import 'package:yaml/yaml.dart';
import '../api/asset.dart' as api;
import '../utils/yaml.dart';
import 'link_mode.dart';
import 'target.dart';
abstract class AssetPath implements api.AssetPath {
factory AssetPath(String pathType, Uri? uri) {
switch (pathType) {
case AssetAbsolutePath._pathTypeValue:
return AssetAbsolutePath(uri!);
case AssetSystemPath._pathTypeValue:
return AssetSystemPath(uri!);
case AssetInExecutable._pathTypeValue:
return AssetInExecutable();
case AssetInProcess._pathTypeValue:
return AssetInProcess();
}
throw FormatException('Unknown pathType: $pathType.');
}
factory AssetPath.fromYaml(YamlMap yamlMap) {
final pathType = as<String>(yamlMap[_pathTypeKey]);
final uriString = as<String?>(yamlMap[_uriKey]);
final uri = uriString != null ? Uri(path: uriString) : null;
return AssetPath(pathType, uri);
}
Map<String, Object> toYaml();
static const _pathTypeKey = 'path_type';
static const _uriKey = 'uri';
}
/// Asset at absolute path [uri].
class AssetAbsolutePath implements AssetPath, api.AssetAbsolutePath {
@override
final Uri uri;
AssetAbsolutePath(this.uri);
static const _pathTypeValue = 'absolute';
@override
Map<String, Object> toYaml() => {
AssetPath._pathTypeKey: _pathTypeValue,
AssetPath._uriKey: uri.toFilePath(),
};
@override
int get hashCode => Object.hash(uri, 133711);
@override
bool operator ==(Object other) {
if (other is! AssetAbsolutePath) {
return false;
}
return uri == other.uri;
}
}
/// Asset is avaliable on the system `PATH`.
///
/// [uri] only contains a file name.
class AssetSystemPath implements AssetPath, api.AssetSystemPath {
@override
final Uri uri;
AssetSystemPath(this.uri);
static const _pathTypeValue = 'system';
@override
Map<String, Object> toYaml() => {
AssetPath._pathTypeKey: _pathTypeValue,
AssetPath._uriKey: uri.toFilePath(),
};
@override
int get hashCode => Object.hash(uri, 133723);
@override
bool operator ==(Object other) {
if (other is! AssetSystemPath) {
return false;
}
return uri == other.uri;
}
}
/// Asset is loaded in the process and symbols are available through
/// `DynamicLibrary.process()`.
class AssetInProcess implements AssetPath, api.AssetInProcess {
AssetInProcess._();
static final AssetInProcess _singleton = AssetInProcess._();
factory AssetInProcess() => _singleton;
static const _pathTypeValue = 'process';
@override
Map<String, Object> toYaml() => {
AssetPath._pathTypeKey: _pathTypeValue,
};
}
/// Asset is embedded in executable and symbols are available through
/// `DynamicLibrary.executable()`.
class AssetInExecutable implements AssetPath, api.AssetInExecutable {
AssetInExecutable._();
static final AssetInExecutable _singleton = AssetInExecutable._();
factory AssetInExecutable() => _singleton;
static const _pathTypeValue = 'executable';
@override
Map<String, Object> toYaml() => {
AssetPath._pathTypeKey: _pathTypeValue,
};
}
class Asset implements api.Asset {
@override
final LinkMode linkMode;
@override
final String id;
@override
final Target target;
@override
final AssetPath path;
Asset({
required this.id,
required this.linkMode,
required this.target,
required this.path,
});
factory Asset.fromYaml(YamlMap yamlMap) => Asset(
id: as<String>(yamlMap[_idKey]),
path: AssetPath.fromYaml(as<YamlMap>(yamlMap[_pathKey])),
target: Target.fromString(as<String>(yamlMap[_targetKey])),
linkMode: LinkMode.fromName(as<String>(yamlMap[_linkModeKey])),
);
static List<Asset> listFromYamlString(String yaml) {
final yamlObject = loadYaml(yaml);
if (yamlObject == null) {
return [];
}
return [
for (final yamlElement in as<YamlList>(yamlObject))
Asset.fromYaml(as<YamlMap>(yamlElement)),
];
}
static List<Asset> listFromYamlList(YamlList yamlList) => [
for (final yamlElement in yamlList)
Asset.fromYaml(as<YamlMap>(yamlElement)),
];
Asset copyWith({
LinkMode? linkMode,
String? id,
Target? target,
AssetPath? path,
}) =>
Asset(
id: id ?? this.id,
linkMode: linkMode ?? this.linkMode,
target: target ?? this.target,
path: path ?? this.path,
);
@override
bool operator ==(Object other) {
if (other is! Asset) {
return false;
}
return other.id == id &&
other.linkMode == linkMode &&
other.target == target &&
other.path == path;
}
@override
int get hashCode => Object.hash(id, linkMode, target, path);
Map<String, Object> toYaml() => {
_idKey: id,
_linkModeKey: linkMode.name,
_pathKey: path.toYaml(),
_targetKey: target.toString(),
};
static const _idKey = 'id';
static const _linkModeKey = 'link_mode';
static const _pathKey = 'path';
static const _targetKey = 'target';
// Future<bool> exists() => path.exists();
@override
String toString() => 'Asset(${toYaml()})';
}
extension AssetIterable on Iterable<Asset> {
List<Object> toYaml() => [for (final item in this) item.toYaml()];
String toYamlString() => yamlEncode(toYaml());
}