blob: 1b4e637f24943051821494e042d2378ad0348b58 [file] [log] [blame] [edit]
// 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 'package:collection/collection.dart';
import 'hooks/syntax.g.dart';
/// An encoded asset.
///
/// Use a protocol extension such as `package:code_assets` or
/// `package:data_assets` to encode and decode assets.
final class EncodedAsset {
/// The type of the asset (e.g. whether it's a code asset, data asset or ...)
final String type;
/// The json encoding of the asset.
final UnmodifiableMapView<String, Object?> encoding;
/// The path of the [encoding] in a larger JSON.
///
/// If provided, used for more precise error messages.
final List<Object>? encodingJsonPath;
/// Creates an [EncodedAsset].
EncodedAsset(
this.type,
Map<String, Object?> encoding, {
this.encodingJsonPath,
}) : encoding = UnmodifiableMapView(
// It would be better if `encoding` would be deep copied.
// https://github.com/dart-lang/native/issues/2045
Map.of(encoding),
);
/// Decode an [EncodedAsset] from json.
factory EncodedAsset.fromJson(
Map<String, Object?> json, [
List<Object>? path,
]) => EncodedAssetSyntaxExtension.fromSyntax(
AssetSyntax.fromJson(json, path: path ?? []),
);
/// Encode this [EncodedAsset] tojson.
Map<String, Object?> toJson() => toSyntax().json;
@override
String toString() => 'EncodedAsset($type, $encoding)';
@override
int get hashCode => Object.hash(type, const DeepCollectionEquality().hash);
@override
bool operator ==(Object other) =>
other is EncodedAsset &&
type == other.type &&
const DeepCollectionEquality().equals(encoding, other.encoding);
}
/// Extension methods for [EncodedAsset] to convert to and from syntax
/// nodes.
extension EncodedAssetSyntaxExtension on EncodedAsset {
/// Creates a [EncodedAsset] from a [AssetSyntax] node.
static EncodedAsset fromSyntax(AssetSyntax syntaxNode) => EncodedAsset(
syntaxNode.type,
syntaxNode.encoding?.json ?? {},
encodingJsonPath: syntaxNode.encoding?.path,
);
/// Converts this [EncodedAsset] to a [AssetSyntax] node.
AssetSyntax toSyntax() {
final path = switch (encodingJsonPath) {
// Remove the last element from the encoding path.
final List<Object> l => l.sublist(0, l.length - 1),
null => <Object>[],
};
return AssetSyntax(
encoding: JsonObjectSyntax.fromJson(Map.of(encoding)),
type: type,
path: path,
);
}
}