|  | // 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 'dart:convert'; | 
|  |  | 
|  | import 'exceptions.dart'; | 
|  |  | 
|  | /// A base class for (spec-generated) classes that represent the `body` of a an | 
|  | /// event. | 
|  | abstract class EventBody { | 
|  | static bool canParse(Object? obj) => obj is Map<String, Object?>?; | 
|  | } | 
|  |  | 
|  | /// A generic event body class that just supplies an object directly. | 
|  | /// | 
|  | /// Used to support custom events sent by the debug adapter such as 'dart.log'. | 
|  | /// | 
|  | /// The supplied [body] must be convertible to JSON. | 
|  | class RawEventBody extends EventBody { | 
|  | final Object body; | 
|  |  | 
|  | RawEventBody(this.body) | 
|  | : assert(() { | 
|  | try { | 
|  | jsonEncode(body); | 
|  | return true; | 
|  | } catch (e) { | 
|  | return false; | 
|  | } | 
|  | }(), 'body should be JSON encodable'); | 
|  |  | 
|  | Object toJson() => body; | 
|  | } | 
|  |  | 
|  | /// A generic arguments class that just supplies the arguments map directly. | 
|  | /// | 
|  | /// Used to support custom requests that may be provided by other implementing | 
|  | /// adapters that are not known at compile time by DDS/base DAP. | 
|  | class RawRequestArguments extends RequestArguments { | 
|  | final Map<String, Object?> args; | 
|  |  | 
|  | RawRequestArguments.fromMap(this.args); | 
|  |  | 
|  | static RawRequestArguments fromJson(Map<String, Object?> obj) => | 
|  | RawRequestArguments.fromMap(obj); | 
|  | } | 
|  |  | 
|  | /// A base class for (spec-generated) classes that represent the `arguments` of | 
|  | /// a request. | 
|  | abstract class RequestArguments { | 
|  | static bool canParse(Object? obj) => obj is Map<String, Object?>?; | 
|  | } | 
|  |  | 
|  | /// A helper for reading arguments for DAP requests from the client. | 
|  | class DebugAdapterArgumentReader { | 
|  | final String request; | 
|  |  | 
|  | DebugAdapterArgumentReader(this.request); | 
|  |  | 
|  | /// Reads a value of type [T] from [field] in [obj]. | 
|  | T read<T>( | 
|  | Map<String, Object?> obj, | 
|  | String field, | 
|  | ) { | 
|  | final value = obj[field]; | 
|  | if (value is! T) { | 
|  | throw DebugAdapterInvalidArgumentException( | 
|  | requestName: request, | 
|  | argumentName: field, | 
|  | expectedType: T, | 
|  | actualType: value.runtimeType, | 
|  | actualValue: value, | 
|  | ); | 
|  | } | 
|  | return obj[field] as T; | 
|  | } | 
|  |  | 
|  | /// Reads a List of values of type [T] from [field] in [obj]. | 
|  | List<T> readList<T>( | 
|  | Map<String, Object?> obj, | 
|  | String field, | 
|  | ) { | 
|  | final value = obj[field]; | 
|  | if (value is! List || !value.every((element) => element is T)) { | 
|  | throw DebugAdapterInvalidArgumentException( | 
|  | requestName: request, | 
|  | argumentName: field, | 
|  | expectedType: List<T>, | 
|  | actualType: value.runtimeType, | 
|  | actualValue: value, | 
|  | ); | 
|  | } | 
|  | return (obj[field] as List<Object?>).cast<T>(); | 
|  | } | 
|  |  | 
|  | /// Reads an optional List of values of type [T] from [field] in [obj]. | 
|  | List<T>? readOptionalList<T>( | 
|  | Map<String, Object?> obj, | 
|  | String field, | 
|  | ) { | 
|  | return obj.containsKey(field) ? readList<T>(obj, field) : null; | 
|  | } | 
|  |  | 
|  | /// Reads an optional Map of types [K],[V] from [field] in [obj]. | 
|  | Map<K, V>? readOptionalMap<K, V>( | 
|  | Map<String, Object?> obj, | 
|  | String field, | 
|  | ) { | 
|  | return obj.containsKey(field) ? readMap<K, V>(obj, field) : null; | 
|  | } | 
|  |  | 
|  | /// Reads a Map of types [K],[V] from [field] in [obj]. | 
|  | Map<K, V> readMap<K, V>( | 
|  | Map<String, Object?> obj, | 
|  | String field, | 
|  | ) { | 
|  | final value = obj[field]; | 
|  | if (value is! Map || | 
|  | !value.entries.every((entry) => entry.key is K && entry.value is V)) { | 
|  | throw DebugAdapterInvalidArgumentException( | 
|  | requestName: request, | 
|  | argumentName: field, | 
|  | expectedType: Map<K, V>, | 
|  | actualType: value.runtimeType, | 
|  | actualValue: value, | 
|  | ); | 
|  | } | 
|  | return (obj[field] as Map<Object?, Object?>).cast<K, V>(); | 
|  | } | 
|  | } |