| // Copyright (c) 2025, 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. | |
| // This file is generated, do not edit. | |
| // File generated by pkgs/pub_formats/tool/generate.dart. | |
| // Must be rerun when pkgs/pub_formats/doc/schema/ is modified. | |
| // ignore_for_file: unused_element, public_member_api_docs | |
| import 'dart:io'; | |
| class DependencySourceSyntax extends JsonObjectSyntax { | |
| DependencySourceSyntax.fromJson(super.json, {super.path = const []}) | |
| : super.fromJson(); | |
| DependencySourceSyntax({super.path = const []}) : super(); | |
| @override | |
| List<String> validate() => [...super.validate()]; | |
| @override | |
| String toString() => 'DependencySourceSyntax($json)'; | |
| } | |
| class EnvironmentSyntax extends JsonObjectSyntax { | |
| EnvironmentSyntax.fromJson(super.json, {super.path = const []}) | |
| : super.fromJson(); | |
| EnvironmentSyntax({ | |
| String? flutter, | |
| required String sdk, | |
| super.path = const [], | |
| }) : super() { | |
| _flutter = flutter; | |
| _sdk = sdk; | |
| json.sortOnKey(); | |
| } | |
| String? get flutter => _reader.get<String?>('flutter'); | |
| set _flutter(String? value) { | |
| json.setOrRemove('flutter', value); | |
| } | |
| List<String> _validateFlutter() => _reader.validate<String?>('flutter'); | |
| String get sdk => _reader.get<String>('sdk'); | |
| set _sdk(String value) { | |
| json.setOrRemove('sdk', value); | |
| } | |
| List<String> _validateSdk() => _reader.validate<String>('sdk'); | |
| @override | |
| List<String> validate() => [ | |
| ...super.validate(), | |
| ..._validateFlutter(), | |
| ..._validateSdk(), | |
| ]; | |
| @override | |
| String toString() => 'EnvironmentSyntax($json)'; | |
| } | |
| class GitSyntax extends JsonObjectSyntax { | |
| GitSyntax.fromJson(super.json, {super.path = const []}) : super.fromJson(); | |
| GitSyntax({ | |
| String? path$, | |
| String? ref, | |
| required String url, | |
| super.path = const [], | |
| }) : super() { | |
| _path$ = path$; | |
| _ref = ref; | |
| _url = url; | |
| json.sortOnKey(); | |
| } | |
| String? get path$ => _reader.get<String?>('path'); | |
| set _path$(String? value) { | |
| json.setOrRemove('path', value); | |
| } | |
| List<String> _validatePath$() => _reader.validate<String?>('path'); | |
| String? get ref => _reader.get<String?>('ref'); | |
| set _ref(String? value) { | |
| json.setOrRemove('ref', value); | |
| } | |
| List<String> _validateRef() => _reader.validate<String?>('ref'); | |
| String get url => _reader.get<String>('url'); | |
| set _url(String value) { | |
| json.setOrRemove('url', value); | |
| } | |
| List<String> _validateUrl() => _reader.validate<String>('url'); | |
| @override | |
| List<String> validate() => [ | |
| ...super.validate(), | |
| ..._validatePath$(), | |
| ..._validateRef(), | |
| ..._validateUrl(), | |
| ]; | |
| @override | |
| String toString() => 'GitSyntax($json)'; | |
| } | |
| class GitDependencySourceSyntax extends DependencySourceSyntax { | |
| GitDependencySourceSyntax.fromJson(super.json, {super.path}) | |
| : super.fromJson(); | |
| GitDependencySourceSyntax({required GitSyntax git, super.path = const []}) | |
| : super() { | |
| _git = git; | |
| json.sortOnKey(); | |
| } | |
| /// Setup all fields for [GitDependencySourceSyntax] that are not in | |
| /// [DependencySourceSyntax]. | |
| void setup({required GitSyntax git}) { | |
| _git = git; | |
| json.sortOnKey(); | |
| } | |
| GitSyntax get git { | |
| final jsonValue = _reader.map$('git'); | |
| return GitSyntax.fromJson(jsonValue, path: [...path, 'git']); | |
| } | |
| set _git(GitSyntax value) { | |
| json['git'] = value.json; | |
| } | |
| List<String> _validateGit() { | |
| final mapErrors = _reader.validate<Map<String, Object?>>('git'); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| return git.validate(); | |
| } | |
| @override | |
| List<String> validate() => [...super.validate(), ..._validateGit()]; | |
| @override | |
| String toString() => 'GitDependencySourceSyntax($json)'; | |
| } | |
| class HooksSyntax extends JsonObjectSyntax { | |
| HooksSyntax.fromJson(super.json, {super.path = const []}) : super.fromJson(); | |
| HooksSyntax({ | |
| Map<String, Map<String, Object?>>? userDefines, | |
| super.path = const [], | |
| }) : super() { | |
| _userDefines = userDefines; | |
| json.sortOnKey(); | |
| } | |
| static final _userDefinesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); | |
| Map<String, Map<String, Object?>>? get userDefines => | |
| _reader.optionalMap<Map<String, Object?>>( | |
| 'user_defines', | |
| keyPattern: _userDefinesKeyPattern, | |
| ); | |
| set _userDefines(Map<String, Map<String, Object?>>? value) { | |
| _checkArgumentMapKeys(value, keyPattern: _userDefinesKeyPattern); | |
| json.setOrRemove('user_defines', value); | |
| } | |
| List<String> _validateUserDefines() => | |
| _reader.validateOptionalMap<Map<String, Object?>>( | |
| 'user_defines', | |
| keyPattern: _userDefinesKeyPattern, | |
| ); | |
| @override | |
| List<String> validate() => [...super.validate(), ..._validateUserDefines()]; | |
| @override | |
| String toString() => 'HooksSyntax($json)'; | |
| } | |
| class HostedDependencySourceSyntax extends DependencySourceSyntax { | |
| HostedDependencySourceSyntax.fromJson(super.json, {super.path}) | |
| : super.fromJson(); | |
| HostedDependencySourceSyntax({ | |
| String? hosted, | |
| required String version, | |
| super.path = const [], | |
| }) : super() { | |
| _hosted = hosted; | |
| _version = version; | |
| json.sortOnKey(); | |
| } | |
| /// Setup all fields for [HostedDependencySourceSyntax] that are not in | |
| /// [DependencySourceSyntax]. | |
| void setup({required String? hosted, required String version}) { | |
| _hosted = hosted; | |
| _version = version; | |
| json.sortOnKey(); | |
| } | |
| String? get hosted => _reader.get<String?>('hosted'); | |
| set _hosted(String? value) { | |
| json.setOrRemove('hosted', value); | |
| } | |
| List<String> _validateHosted() => _reader.validate<String?>('hosted'); | |
| String get version => _reader.get<String>('version'); | |
| set _version(String value) { | |
| json.setOrRemove('version', value); | |
| } | |
| List<String> _validateVersion() => _reader.validate<String>('version'); | |
| @override | |
| List<String> validate() => [ | |
| ...super.validate(), | |
| ..._validateHosted(), | |
| ..._validateVersion(), | |
| ]; | |
| @override | |
| String toString() => 'HostedDependencySourceSyntax($json)'; | |
| } | |
| class PathDependencySourceSyntax extends DependencySourceSyntax { | |
| PathDependencySourceSyntax.fromJson(super.json, {super.path}) | |
| : super.fromJson(); | |
| PathDependencySourceSyntax({required String path$, super.path = const []}) | |
| : super() { | |
| _path$ = path$; | |
| json.sortOnKey(); | |
| } | |
| /// Setup all fields for [PathDependencySourceSyntax] that are not in | |
| /// [DependencySourceSyntax]. | |
| void setup({required String path$}) { | |
| _path$ = path$; | |
| json.sortOnKey(); | |
| } | |
| String get path$ => _reader.get<String>('path'); | |
| set _path$(String value) { | |
| json.setOrRemove('path', value); | |
| } | |
| List<String> _validatePath$() => _reader.validate<String>('path'); | |
| @override | |
| List<String> validate() => [...super.validate(), ..._validatePath$()]; | |
| @override | |
| String toString() => 'PathDependencySourceSyntax($json)'; | |
| } | |
| class PubspecYamlFileSyntax extends JsonObjectSyntax { | |
| PubspecYamlFileSyntax.fromJson(super.json, {super.path = const []}) | |
| : super.fromJson(); | |
| PubspecYamlFileSyntax({ | |
| Map<String, DependencySourceSyntax>? dependencies, | |
| Map<String, DependencySourceSyntax>? dependencyOverrides, | |
| String? description, | |
| Map<String, DependencySourceSyntax>? devDependencies, | |
| String? documentation, | |
| required EnvironmentSyntax environment, | |
| Map<String, String?>? executables, | |
| String? homepage, | |
| HooksSyntax? hooks, | |
| String? issueTracker, | |
| required String name, | |
| String? publishTo, | |
| String? repository, | |
| String? version, | |
| super.path = const [], | |
| }) : super() { | |
| this.dependencies = dependencies; | |
| this.dependencyOverrides = dependencyOverrides; | |
| this.description = description; | |
| this.devDependencies = devDependencies; | |
| this.documentation = documentation; | |
| this.environment = environment; | |
| this.executables = executables; | |
| this.homepage = homepage; | |
| this.hooks = hooks; | |
| this.issueTracker = issueTracker; | |
| this.name = name; | |
| this.publishTo = publishTo; | |
| this.repository = repository; | |
| this.version = version; | |
| json.sortOnKey(); | |
| } | |
| static final _dependenciesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); | |
| Map<String, DependencySourceSyntax>? get dependencies { | |
| final jsonValue = _reader.optionalMap( | |
| 'dependencies', | |
| keyPattern: _dependenciesKeyPattern, | |
| ); | |
| if (jsonValue == null) { | |
| return null; | |
| } | |
| return { | |
| for (final MapEntry(:key, :value) in jsonValue.entries) | |
| key: DependencySourceSyntax.fromJson( | |
| value as Map<String, Object?>, | |
| path: [...path, key], | |
| ), | |
| }; | |
| } | |
| set dependencies(Map<String, DependencySourceSyntax>? value) { | |
| _checkArgumentMapKeys(value, keyPattern: _dependenciesKeyPattern); | |
| if (value == null) { | |
| json.remove('dependencies'); | |
| } else { | |
| json['dependencies'] = { | |
| for (final MapEntry(:key, :value) in value.entries) key: value.json, | |
| }; | |
| } | |
| json.sortOnKey(); | |
| } | |
| List<String> validateDependencies() { | |
| final mapErrors = _reader.validateOptionalMap( | |
| 'dependencies', | |
| keyPattern: _dependenciesKeyPattern, | |
| ); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| final jsonValue = _reader.optionalMap('dependencies'); | |
| if (jsonValue == null) { | |
| return []; | |
| } | |
| final result = <String>[]; | |
| for (final value in dependencies!.values) { | |
| result.addAll(value.validate()); | |
| } | |
| return result; | |
| } | |
| static final _dependencyOverridesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); | |
| Map<String, DependencySourceSyntax>? get dependencyOverrides { | |
| final jsonValue = _reader.optionalMap( | |
| 'dependency_overrides', | |
| keyPattern: _dependencyOverridesKeyPattern, | |
| ); | |
| if (jsonValue == null) { | |
| return null; | |
| } | |
| return { | |
| for (final MapEntry(:key, :value) in jsonValue.entries) | |
| key: DependencySourceSyntax.fromJson( | |
| value as Map<String, Object?>, | |
| path: [...path, key], | |
| ), | |
| }; | |
| } | |
| set dependencyOverrides(Map<String, DependencySourceSyntax>? value) { | |
| _checkArgumentMapKeys(value, keyPattern: _dependencyOverridesKeyPattern); | |
| if (value == null) { | |
| json.remove('dependency_overrides'); | |
| } else { | |
| json['dependency_overrides'] = { | |
| for (final MapEntry(:key, :value) in value.entries) key: value.json, | |
| }; | |
| } | |
| json.sortOnKey(); | |
| } | |
| List<String> validateDependencyOverrides() { | |
| final mapErrors = _reader.validateOptionalMap( | |
| 'dependency_overrides', | |
| keyPattern: _dependencyOverridesKeyPattern, | |
| ); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| final jsonValue = _reader.optionalMap('dependency_overrides'); | |
| if (jsonValue == null) { | |
| return []; | |
| } | |
| final result = <String>[]; | |
| for (final value in dependencyOverrides!.values) { | |
| result.addAll(value.validate()); | |
| } | |
| return result; | |
| } | |
| String? get description => _reader.get<String?>('description'); | |
| set description(String? value) { | |
| json.setOrRemove('description', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateDescription() => | |
| _reader.validate<String?>('description'); | |
| static final _devDependenciesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); | |
| Map<String, DependencySourceSyntax>? get devDependencies { | |
| final jsonValue = _reader.optionalMap( | |
| 'dev_dependencies', | |
| keyPattern: _devDependenciesKeyPattern, | |
| ); | |
| if (jsonValue == null) { | |
| return null; | |
| } | |
| return { | |
| for (final MapEntry(:key, :value) in jsonValue.entries) | |
| key: DependencySourceSyntax.fromJson( | |
| value as Map<String, Object?>, | |
| path: [...path, key], | |
| ), | |
| }; | |
| } | |
| set devDependencies(Map<String, DependencySourceSyntax>? value) { | |
| _checkArgumentMapKeys(value, keyPattern: _devDependenciesKeyPattern); | |
| if (value == null) { | |
| json.remove('dev_dependencies'); | |
| } else { | |
| json['dev_dependencies'] = { | |
| for (final MapEntry(:key, :value) in value.entries) key: value.json, | |
| }; | |
| } | |
| json.sortOnKey(); | |
| } | |
| List<String> validateDevDependencies() { | |
| final mapErrors = _reader.validateOptionalMap( | |
| 'dev_dependencies', | |
| keyPattern: _devDependenciesKeyPattern, | |
| ); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| final jsonValue = _reader.optionalMap('dev_dependencies'); | |
| if (jsonValue == null) { | |
| return []; | |
| } | |
| final result = <String>[]; | |
| for (final value in devDependencies!.values) { | |
| result.addAll(value.validate()); | |
| } | |
| return result; | |
| } | |
| String? get documentation => _reader.get<String?>('documentation'); | |
| set documentation(String? value) { | |
| json.setOrRemove('documentation', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateDocumentation() => | |
| _reader.validate<String?>('documentation'); | |
| EnvironmentSyntax get environment { | |
| final jsonValue = _reader.map$('environment'); | |
| return EnvironmentSyntax.fromJson( | |
| jsonValue, | |
| path: [...path, 'environment'], | |
| ); | |
| } | |
| set environment(EnvironmentSyntax value) { | |
| json['environment'] = value.json; | |
| json.sortOnKey(); | |
| } | |
| List<String> validateEnvironment() { | |
| final mapErrors = _reader.validate<Map<String, Object?>>('environment'); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| return environment.validate(); | |
| } | |
| static final _executablesKeyPattern = RegExp( | |
| r'^[a-zA-Z_]\w*(-[a-zA-Z_]\w*)*$', | |
| ); | |
| static final _executablesValuePattern = RegExp(r'^[^/\\]*$'); | |
| Map<String, String?>? get executables { | |
| final value = _reader.optionalMap<String?>( | |
| 'executables', | |
| keyPattern: _executablesKeyPattern, | |
| ); | |
| if (value == null) { | |
| return value; | |
| } | |
| final valueErrors = _reader.validateMapStringElements( | |
| value, | |
| 'executables', | |
| valuePattern: _executablesValuePattern, | |
| ); | |
| if (valueErrors.isNotEmpty) { | |
| throw FormatException(valueErrors.join('\n')); | |
| } | |
| return value; | |
| } | |
| set executables(Map<String, String?>? value) { | |
| _checkArgumentMapKeys(value, keyPattern: _executablesKeyPattern); | |
| _checkArgumentMapStringElements( | |
| value, | |
| valuePattern: _executablesValuePattern, | |
| ); | |
| json.setOrRemove('executables', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateExecutables() { | |
| final mapErrors = _reader.validateOptionalMap<String?>( | |
| 'executables', | |
| keyPattern: _executablesKeyPattern, | |
| ); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| final value = _reader.optionalMap<String?>('executables'); | |
| if (value == null) { | |
| return []; | |
| } | |
| return _reader.validateMapStringElements( | |
| value, | |
| 'executables', | |
| valuePattern: _executablesValuePattern, | |
| ); | |
| } | |
| String? get homepage => _reader.get<String?>('homepage'); | |
| set homepage(String? value) { | |
| json.setOrRemove('homepage', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateHomepage() => _reader.validate<String?>('homepage'); | |
| HooksSyntax? get hooks { | |
| final jsonValue = _reader.optionalMap('hooks'); | |
| if (jsonValue == null) return null; | |
| return HooksSyntax.fromJson(jsonValue, path: [...path, 'hooks']); | |
| } | |
| set hooks(HooksSyntax? value) { | |
| json.setOrRemove('hooks', value?.json); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateHooks() { | |
| final mapErrors = _reader.validate<Map<String, Object?>?>('hooks'); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| return hooks?.validate() ?? []; | |
| } | |
| String? get issueTracker => _reader.get<String?>('issue_tracker'); | |
| set issueTracker(String? value) { | |
| json.setOrRemove('issue_tracker', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateIssueTracker() => | |
| _reader.validate<String?>('issue_tracker'); | |
| static final _namePattern = RegExp(r'^[a-zA-Z_]\w*$'); | |
| String get name => _reader.string('name', _namePattern); | |
| set name(String value) { | |
| if (!_namePattern.hasMatch(value)) { | |
| throw ArgumentError.value( | |
| value, | |
| 'value', | |
| 'Value does not satisfy pattern: ${_namePattern.pattern}.', | |
| ); | |
| } | |
| json.setOrRemove('name', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateName() => _reader.validateString('name', _namePattern); | |
| String? get publishTo => _reader.get<String?>('publish_to'); | |
| set publishTo(String? value) { | |
| json.setOrRemove('publish_to', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validatePublishTo() => _reader.validate<String?>('publish_to'); | |
| String? get repository => _reader.get<String?>('repository'); | |
| set repository(String? value) { | |
| json.setOrRemove('repository', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateRepository() => _reader.validate<String?>('repository'); | |
| static final _versionPattern = RegExp( | |
| r'^[0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9.\-]+)?(?:\+[a-zA-Z0-9.\-]+)?$', | |
| ); | |
| String? get version => _reader.optionalString('version', _versionPattern); | |
| set version(String? value) { | |
| if (value != null && !_versionPattern.hasMatch(value)) { | |
| throw ArgumentError.value( | |
| value, | |
| 'value', | |
| 'Value does not satisfy pattern: ${_versionPattern.pattern}.', | |
| ); | |
| } | |
| json.setOrRemove('version', value); | |
| json.sortOnKey(); | |
| } | |
| List<String> validateVersion() => | |
| _reader.validateOptionalString('version', _versionPattern); | |
| @override | |
| List<String> validate() => [ | |
| ...super.validate(), | |
| ...validateDependencies(), | |
| ...validateDependencyOverrides(), | |
| ...validateDescription(), | |
| ...validateDevDependencies(), | |
| ...validateDocumentation(), | |
| ...validateEnvironment(), | |
| ...validateExecutables(), | |
| ...validateHomepage(), | |
| ...validateHooks(), | |
| ...validateIssueTracker(), | |
| ...validateName(), | |
| ...validatePublishTo(), | |
| ...validateRepository(), | |
| ...validateVersion(), | |
| ]; | |
| @override | |
| String toString() => 'PubspecYamlFileSyntax($json)'; | |
| } | |
| class SdkDependencySourceSyntax extends DependencySourceSyntax { | |
| SdkDependencySourceSyntax.fromJson(super.json, {super.path}) | |
| : super.fromJson(); | |
| SdkDependencySourceSyntax({required String sdk, super.path = const []}) | |
| : super() { | |
| _sdk = sdk; | |
| json.sortOnKey(); | |
| } | |
| /// Setup all fields for [SdkDependencySourceSyntax] that are not in | |
| /// [DependencySourceSyntax]. | |
| void setup({required String sdk}) { | |
| _sdk = sdk; | |
| json.sortOnKey(); | |
| } | |
| String get sdk => _reader.get<String>('sdk'); | |
| set _sdk(String value) { | |
| json.setOrRemove('sdk', value); | |
| } | |
| List<String> _validateSdk() => _reader.validate<String>('sdk'); | |
| @override | |
| List<String> validate() => [...super.validate(), ..._validateSdk()]; | |
| @override | |
| String toString() => 'SdkDependencySourceSyntax($json)'; | |
| } | |
| class JsonObjectSyntax { | |
| final Map<String, Object?> json; | |
| final List<Object> path; | |
| _JsonReader get _reader => _JsonReader(json, path); | |
| JsonObjectSyntax({this.path = const []}) : json = {}; | |
| JsonObjectSyntax.fromJson(this.json, {this.path = const []}); | |
| List<String> validate() => []; | |
| } | |
| class _JsonReader { | |
| /// The JSON Object this reader is reading. | |
| final Map<String, Object?> json; | |
| /// The path traversed by readers of the surrounding JSON. | |
| /// | |
| /// Contains [String] property keys and [int] indices. | |
| /// | |
| /// This is used to give more precise error messages. | |
| final List<Object> path; | |
| _JsonReader(this.json, this.path); | |
| T get<T extends Object?>(String key) { | |
| final value = json[key]; | |
| if (value is T) return value; | |
| throwFormatException(value, [key], expectedType: T); | |
| } | |
| List<String> validate<T extends Object?>(String key) { | |
| final value = json[key]; | |
| if (value is T) return []; | |
| return [ | |
| errorString(value, [key], expectedType: T), | |
| ]; | |
| } | |
| List<T> list<T extends Object?>(String key) => | |
| _castList<T>(get<List<Object?>>(key), key); | |
| List<String> validateList<T extends Object?>(String key) { | |
| final listErrors = validate<List<Object?>>(key); | |
| if (listErrors.isNotEmpty) { | |
| return listErrors; | |
| } | |
| return _validateListElements(get<List<Object?>>(key), key); | |
| } | |
| List<T>? optionalList<T extends Object?>(String key) => | |
| switch (get<List<Object?>?>(key)?.cast<T>()) { | |
| null => null, | |
| final l => _castList<T>(l, key), | |
| }; | |
| List<String> validateOptionalList<T extends Object?>(String key) { | |
| final listErrors = validate<List<Object?>?>(key); | |
| if (listErrors.isNotEmpty) { | |
| return listErrors; | |
| } | |
| final list = get<List<Object?>?>(key); | |
| if (list == null) { | |
| return []; | |
| } | |
| return _validateListElements(list, key); | |
| } | |
| /// [List.cast] but with [FormatException]s. | |
| List<T> _castList<T extends Object?>(List<Object?> list, String key) { | |
| for (final (index, value) in list.indexed) { | |
| if (value is! T) { | |
| throwFormatException(value, [key, index], expectedType: T); | |
| } | |
| } | |
| return list.cast(); | |
| } | |
| List<String> _validateListElements<T extends Object?>( | |
| List<Object?> list, | |
| String key, | |
| ) { | |
| final result = <String>[]; | |
| for (final (index, value) in list.indexed) { | |
| if (value is! T) { | |
| result.add(errorString(value, [key, index], expectedType: T)); | |
| } | |
| } | |
| return result; | |
| } | |
| Map<String, T> map$<T extends Object?>(String key, {RegExp? keyPattern}) { | |
| final map = get<Map<String, Object?>>(key); | |
| final keyErrors = _validateMapKeys(map, key, keyPattern: keyPattern); | |
| if (keyErrors.isNotEmpty) { | |
| throw FormatException(keyErrors.join('\n')); | |
| } | |
| return _castMap<T>(map, key); | |
| } | |
| List<String> validateMap<T extends Object?>( | |
| String key, { | |
| RegExp? keyPattern, | |
| }) { | |
| final mapErrors = validate<Map<String, Object?>>(key); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| final map = get<Map<String, Object?>>(key); | |
| return [ | |
| ..._validateMapKeys(map, key, keyPattern: keyPattern), | |
| ..._validateMapElements<T>(map, key), | |
| ]; | |
| } | |
| Map<String, T>? optionalMap<T extends Object?>( | |
| String key, { | |
| RegExp? keyPattern, | |
| }) { | |
| final map = get<Map<String, Object?>?>(key); | |
| if (map == null) return null; | |
| final keyErrors = _validateMapKeys(map, key, keyPattern: keyPattern); | |
| if (keyErrors.isNotEmpty) { | |
| throw FormatException(keyErrors.join('\n')); | |
| } | |
| return _castMap<T>(map, key); | |
| } | |
| List<String> validateOptionalMap<T extends Object?>( | |
| String key, { | |
| RegExp? keyPattern, | |
| }) { | |
| final mapErrors = validate<Map<String, Object?>?>(key); | |
| if (mapErrors.isNotEmpty) { | |
| return mapErrors; | |
| } | |
| final map = get<Map<String, Object?>?>(key); | |
| if (map == null) { | |
| return []; | |
| } | |
| return [ | |
| ..._validateMapKeys(map, key, keyPattern: keyPattern), | |
| ..._validateMapElements<T>(map, key), | |
| ]; | |
| } | |
| /// [Map.cast] but with [FormatException]s. | |
| Map<String, T> _castMap<T extends Object?>( | |
| Map<String, Object?> map_, | |
| String parentKey, | |
| ) { | |
| for (final MapEntry(:key, :value) in map_.entries) { | |
| if (value is! T) { | |
| throwFormatException(value, [parentKey, key], expectedType: T); | |
| } | |
| } | |
| return map_.cast(); | |
| } | |
| List<String> _validateMapKeys( | |
| Map<String, Object?> map_, | |
| String parentKey, { | |
| required RegExp? keyPattern, | |
| }) { | |
| if (keyPattern == null) return []; | |
| final result = <String>[]; | |
| for (final key in map_.keys) { | |
| if (!keyPattern.hasMatch(key)) { | |
| result.add( | |
| keyErrorString(key, pattern: keyPattern, pathExtension: [parentKey]), | |
| ); | |
| } | |
| } | |
| return result; | |
| } | |
| List<String> _validateMapElements<T extends Object?>( | |
| Map<String, Object?> map_, | |
| String parentKey, | |
| ) { | |
| final result = <String>[]; | |
| for (final MapEntry(:key, :value) in map_.entries) { | |
| if (value is! T) { | |
| result.add(errorString(value, [parentKey, key], expectedType: T)); | |
| } | |
| } | |
| return result; | |
| } | |
| List<String> validateMapStringElements<T extends Object?>( | |
| Map<String, String?> map_, | |
| String parentKey, { | |
| RegExp? valuePattern, | |
| }) { | |
| final result = <String>[]; | |
| for (final MapEntry(:key, :value) in map_.entries) { | |
| if (value != null && | |
| valuePattern != null && | |
| !valuePattern.hasMatch(value)) { | |
| result.add( | |
| errorString( | |
| value, | |
| [parentKey, key], | |
| expectedType: T, | |
| pattern: valuePattern, | |
| ), | |
| ); | |
| } | |
| } | |
| return result; | |
| } | |
| String string(String key, RegExp? pattern) { | |
| final value = get<String>(key); | |
| if (pattern != null && !pattern.hasMatch(value)) { | |
| throwFormatException( | |
| value, | |
| [key], | |
| expectedType: String, | |
| pattern: pattern, | |
| ); | |
| } | |
| return value; | |
| } | |
| String? optionalString(String key, RegExp? pattern) { | |
| final value = get<String?>(key); | |
| if (value == null) return null; | |
| if (pattern != null && !pattern.hasMatch(value)) { | |
| throwFormatException( | |
| value, | |
| [key], | |
| expectedType: String, | |
| pattern: pattern, | |
| ); | |
| } | |
| return value; | |
| } | |
| List<String> validateString(String key, RegExp? pattern) { | |
| final errors = validate<String>(key); | |
| if (errors.isNotEmpty) { | |
| return errors; | |
| } | |
| final value = get<String>(key); | |
| if (pattern != null && !pattern.hasMatch(value)) { | |
| return [ | |
| errorString(value, [key], expectedType: String, pattern: pattern), | |
| ]; | |
| } | |
| return []; | |
| } | |
| List<String> validateOptionalString(String key, RegExp? pattern) { | |
| final errors = validate<String?>(key); | |
| if (errors.isNotEmpty) { | |
| return errors; | |
| } | |
| final value = get<String?>(key); | |
| if (value == null) return []; | |
| if (pattern != null && !pattern.hasMatch(value)) { | |
| return [ | |
| errorString(value, [key], expectedType: String, pattern: pattern), | |
| ]; | |
| } | |
| return []; | |
| } | |
| List<String>? optionalStringList(String key) => optionalList<String>(key); | |
| List<String> validateOptionalStringList(String key) => | |
| validateOptionalList<String>(key); | |
| List<String> stringList(String key) => list<String>(key); | |
| List<String> validateStringList(String key) => validateList<String>(key); | |
| Uri path$(String key) => _fileSystemPathToUri(get<String>(key)); | |
| List<String> validatePath(String key) => validate<String>(key); | |
| Uri? optionalPath(String key) { | |
| final value = get<String?>(key); | |
| if (value == null) return null; | |
| return _fileSystemPathToUri(value); | |
| } | |
| List<String> validateOptionalPath(String key) => validate<String?>(key); | |
| List<Uri>? optionalPathList(String key) { | |
| final strings = optionalStringList(key); | |
| if (strings == null) { | |
| return null; | |
| } | |
| return [for (final string in strings) _fileSystemPathToUri(string)]; | |
| } | |
| List<String> validateOptionalPathList(String key) => | |
| validateOptionalStringList(key); | |
| static Uri _fileSystemPathToUri(String path) { | |
| if (path.endsWith(Platform.pathSeparator)) { | |
| return Uri.directory(path); | |
| } | |
| return Uri.file(path); | |
| } | |
| String _jsonPathToString(List<Object> pathEnding) => | |
| [...path, ...pathEnding].join('.'); | |
| Never throwFormatException( | |
| Object? value, | |
| List<Object> pathExtension, { | |
| Type? expectedType, | |
| RegExp? pattern, | |
| Set<String>? expectedValues, | |
| }) => _throwFormatException( | |
| value, | |
| [...path, ...pathExtension], | |
| expectedType: expectedType, | |
| pattern: pattern, | |
| expectedValues: expectedValues, | |
| ); | |
| String errorString( | |
| Object? value, | |
| List<Object> pathExtension, { | |
| Type? expectedType, | |
| RegExp? pattern, | |
| Set<String>? expectedValues, | |
| }) => _errorString( | |
| value, | |
| [...path, ...pathExtension], | |
| expectedType: expectedType, | |
| pattern: pattern, | |
| expectedValues: expectedValues, | |
| ); | |
| String keyErrorString( | |
| String key, { | |
| required RegExp pattern, | |
| List<Object> pathExtension = const [], | |
| }) { | |
| final pathString = _jsonPathToString(pathExtension); | |
| return "Unexpected key '$key' in '$pathString'." | |
| ' Expected a key satisfying ${pattern.pattern}.'; | |
| } | |
| /// Traverses a JSON path, returns `null` if the path cannot be traversed. | |
| Object? tryTraverse(List<String> path) { | |
| Object? json = this.json; | |
| for (final key in path) { | |
| if (json is! Map<String, Object?>) { | |
| return null; | |
| } | |
| json = json[key]; | |
| } | |
| return json; | |
| } | |
| } | |
| extension on Map<String, Object?> { | |
| void setOrRemove(String key, Object? value) { | |
| if (value == null) { | |
| remove(key); | |
| } else { | |
| this[key] = value; | |
| } | |
| } | |
| } | |
| extension on List<Uri> { | |
| List<String> toJson() => [for (final uri in this) uri.toFilePath()]; | |
| } | |
| extension<K extends Comparable<K>, V extends Object?> on Map<K, V> { | |
| void sortOnKey() { | |
| final result = <K, V>{}; | |
| final keysSorted = keys.toList()..sort(); | |
| for (final key in keysSorted) { | |
| result[key] = this[key] as V; | |
| } | |
| clear(); | |
| addAll(result); | |
| } | |
| } | |
| void _checkArgumentMapKeys(Map<String, Object?>? map, {RegExp? keyPattern}) { | |
| if (map == null) return; | |
| if (keyPattern == null) return; | |
| for (final key in map.keys) { | |
| if (!keyPattern.hasMatch(key)) { | |
| throw ArgumentError.value( | |
| map, | |
| "Unexpected key '$key'." | |
| ' Expected a key satisfying ${keyPattern.pattern}.', | |
| ); | |
| } | |
| } | |
| } | |
| Never _throwFormatException( | |
| Object? value, | |
| List<Object> path, { | |
| Type? expectedType, | |
| RegExp? pattern, | |
| Set<String>? expectedValues, | |
| }) { | |
| throw FormatException( | |
| _errorString( | |
| value, | |
| path, | |
| expectedType: expectedType, | |
| pattern: pattern, | |
| expectedValues: expectedValues, | |
| ), | |
| ); | |
| } | |
| String _errorString( | |
| Object? value, | |
| List<Object> path, { | |
| Type? expectedType, | |
| RegExp? pattern, | |
| Set<String>? expectedValues, | |
| }) { | |
| final pathString = path.join('.'); | |
| final String expected; | |
| if (expectedValues != null) { | |
| expected = "one of ${expectedValues.map((e) => "'$e'").join(', ')}"; | |
| } else { | |
| final satisfying = pattern == null ? '' : ' satisfying ${pattern.pattern}'; | |
| expected = 'a $expectedType$satisfying'; | |
| } | |
| if (value == null) { | |
| return "No value was provided for '$pathString'." | |
| ' Expected $expected.'; | |
| } | |
| return "Unexpected value '$value' (${value.runtimeType}) for '$pathString'." | |
| ' Expected $expected.'; | |
| } | |
| void _checkArgumentMapStringElements( | |
| Map<String, String?>? map, { | |
| RegExp? valuePattern, | |
| }) { | |
| if (map == null) return; | |
| if (valuePattern == null) return; | |
| for (final entry in map.entries) { | |
| final value = entry.value; | |
| if (value != null && !valuePattern.hasMatch(value)) { | |
| throw ArgumentError.value( | |
| map, | |
| "Unexpected value '$value' under key '${entry.key}'." | |
| ' Expected a value satisfying ${valuePattern.pattern}.', | |
| ); | |
| } | |
| } | |
| } |