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