blob: bd5ffa8daf60dd65c1e3ba5408af2e09c08f8c92 [file] [log] [blame]
// Copyright (c) 2024, 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 'code_asset.dart';
import 'syntax.g.dart';
/// The link mode for a [CodeAsset].
///
/// Known linking modes:
///
/// * [StaticLinking]
/// * [DynamicLoading]
/// * [LookupInProcess]
/// * [LookupInExecutable]
/// * [DynamicLoadingBundled]
/// * [DynamicLoadingSystem]
///
/// See the documentation on the above classes.
abstract final class LinkMode {
const LinkMode._();
/// Constructs a [LinkMode] from the given [json].
///
/// The json is expected to be valid encoding obtained via [LinkMode.toJson].
factory LinkMode.fromJson(Map<String, Object?> json) =>
LinkModeSyntaxExtension.fromSyntax(LinkModeSyntax.fromJson(json));
/// The json representation of this [LinkMode].
///
/// The returned json is stable and can be used in [LinkMode.fromJson] to
/// obtain a [LinkMode] again.
Map<String, Object?> toJson() => toSyntax().json;
}
/// Extension methods for [LinkMode] to convert to and from the syntax model.
extension LinkModeSyntaxExtension on LinkMode {
/// Converts this [LinkMode] to its corresponding [LinkModeSyntax]
/// representation.
LinkModeSyntax toSyntax() => switch (this) {
StaticLinking() => StaticLinkModeSyntax(),
LookupInProcess() => DynamicLoadingProcessLinkModeSyntax(),
LookupInExecutable() => DynamicLoadingExecutableLinkModeSyntax(),
DynamicLoadingBundled() => DynamicLoadingBundleLinkModeSyntax(),
final DynamicLoadingSystem system => DynamicLoadingSystemLinkModeSyntax(
uri: system.uri,
),
_ => throw UnimplementedError('The link mode "$this" is not known'),
};
/// Converts a [LinkModeSyntax] to its corresponding [LinkMode]
/// representation.
static LinkMode fromSyntax(LinkModeSyntax linkMode) => switch (linkMode) {
_ when linkMode.isStaticLinkMode => StaticLinking(),
_ when linkMode.isDynamicLoadingProcessLinkMode => LookupInProcess(),
_ when linkMode.isDynamicLoadingExecutableLinkMode => LookupInExecutable(),
_ when linkMode.isDynamicLoadingBundleLinkMode => DynamicLoadingBundled(),
_ when linkMode.isDynamicLoadingSystemLinkMode => DynamicLoadingSystem(
linkMode.asDynamicLoadingSystemLinkMode.uri,
),
_ => throw FormatException('The link mode "${linkMode.type}" is not known'),
};
}
/// [CodeAsset]s with this [LinkMode] will be loaded at runtime.
///
/// Nothing happens at native code linking time.
///
/// Supported in the Dart and Flutter SDK.
///
/// Note: Dynamic loading is not equal to dynamic linking. Dynamic linking
/// would have to run the linker at compile-time, which is currently not
/// supported in the Dart and Flutter SDK.
abstract final class DynamicLoading extends LinkMode {
DynamicLoading._() : super._();
}
/// [CodeAsset]s with this [LinkMode] will be bundled as dynamic libraries by
/// Dart/Flutter at build time.
///
/// At runtime, the dynamic library will be loaded and the symbols will be
/// looked up in this dynamic library.
///
/// An asset with this link mode must provide a [CodeAsset.file] and it must be
/// a dynamic library.
///
/// The Dart and Flutter SDK will bundle this code in the final application.
final class DynamicLoadingBundled extends DynamicLoading {
DynamicLoadingBundled._() : super._();
static final DynamicLoadingBundled _singleton = DynamicLoadingBundled._();
/// Returns the singleton instance of [DynamicLoadingBundled].
factory DynamicLoadingBundled() => _singleton;
@override
String toString() => 'bundled';
}
/// [CodeAsset]s with this [LinkMode] are expected to be available as dynamic
/// library on the target system `PATH`.
///
/// At buildtime, nothing happens.
///
/// At runtime, the dynamic library will be loaded and the symbols will be
/// looked up in this dynamic library.
final class DynamicLoadingSystem extends DynamicLoading {
/// The [Uri] of the dynamic library on the system.
final Uri uri;
/// Constructs a [DynamicLoadingSystem] with the given [uri].
DynamicLoadingSystem(this.uri) : super._();
static const _typeValue = 'dynamic_loading_system';
@override
int get hashCode => uri.hashCode;
@override
bool operator ==(Object other) =>
other is DynamicLoadingSystem && uri == other.uri;
@override
String toString() => _typeValue;
}
/// [CodeAsset]s with this [LinkMode] are expected to have their symbols
/// available through `DynamicLibrary.process()`.
///
/// At buildtime, nothing happens.
final class LookupInProcess extends DynamicLoading {
LookupInProcess._() : super._();
static final LookupInProcess _singleton = LookupInProcess._();
/// Returns the singleton instance of [LookupInProcess].
factory LookupInProcess() => _singleton;
@override
String toString() => 'process';
}
/// [CodeAsset]s with this [LinkMode] are expected to have their symbols
/// available through `DynamicLibrary.executable()`.
///
/// At buildtime, nothing happens.
final class LookupInExecutable extends DynamicLoading {
LookupInExecutable._() : super._();
static final LookupInExecutable _singleton = LookupInExecutable._();
/// Returns the singleton instance of [LookupInExecutable].
factory LookupInExecutable() => _singleton;
@override
String toString() => 'executable';
}
/// [CodeAsset]s with this [LinkMode] are linked statically.
///
/// An asset with this link mode must provide a [CodeAsset.file] and it must be
/// a static library.
///
/// At native linking time, native function names will be resolved to static
/// libraries.
///
/// Not yet supported in the Dart and Flutter SDK.
// TODO(https://github.com/dart-lang/sdk/issues/49418): Support static linking.
final class StaticLinking extends LinkMode {
const StaticLinking._() : super._();
/// Returns the singleton instance of [StaticLinking].
factory StaticLinking() => _singleton;
static const StaticLinking _singleton = StaticLinking._();
@override
String toString() => 'static';
}