11import 'package:analyzer/dart/constant/value.dart' show DartObject;
2+ import 'package:analyzer/dart/element/type.dart' ;
3+ import 'package:exception_templates/exception_templates.dart' show ErrorOf;
24
35import '../extension/type_methods.dart' ;
46import 'decoder.dart' ;
@@ -12,8 +14,6 @@ class BoolDecoder extends Decoder<bool> {
1214 };
1315}
1416
15- const boolDecoder = BoolDecoder ();
16-
1717class IntDecoder extends Decoder <int > {
1818 const IntDecoder ();
1919 @override
@@ -50,8 +50,6 @@ class NumDecoder extends Decoder<num> {
5050 }
5151}
5252
53- const numDecoder = NumDecoder ();
54-
5553class StringDecoder extends Decoder <String > {
5654 const StringDecoder ();
5755 @override
@@ -61,8 +59,6 @@ class StringDecoder extends Decoder<String> {
6159 };
6260}
6361
64- const stringDecoder = StringDecoder ();
65-
6662class SymbolDecoder extends Decoder <Symbol > {
6763 const SymbolDecoder ();
6864 @override
@@ -72,8 +68,6 @@ class SymbolDecoder extends Decoder<Symbol> {
7268 };
7369}
7470
75- const symbolDecoder = SymbolDecoder ();
76-
7771class TypeDecoder extends Decoder <Type > {
7872 const TypeDecoder ();
7973 @override
@@ -83,7 +77,20 @@ class TypeDecoder extends Decoder<Type> {
8377 };
8478}
8579
86- const typeDecoder = TypeDecoder ();
80+ /// A [Decoder] that can be registered to read a const object with no
81+ /// substructure like a simple annotation. It returns the [value] provided as
82+ /// constructor parameter.
83+ class ValueDecoder <T > extends Decoder <T > {
84+ const ValueDecoder (this .value);
85+
86+ /// The object returned by the method [read] .
87+ final T value;
88+
89+ @override
90+ /// Returns the constant value of type [T]
91+ /// that is provided as constructor parameter.
92+ T read (DartObject obj) => value;
93+ }
8794
8895/// A generic enum decoder
8996class EnumDecoder <E extends Enum > extends Decoder <E > {
@@ -98,3 +105,45 @@ class EnumDecoder<E extends Enum> extends Decoder<E> {
98105 _ => throw readError (obj),
99106 };
100107}
108+
109+ /// A callback which returns a [Record] given the [positional] and [named]
110+ /// record fields.
111+ typedef RecordFactory <T extends Record > =
112+ T Function ({
113+ required List <DartObject > positional,
114+ required Map <String , DartObject > named,
115+ });
116+
117+ class RecordDecoder <T extends Record > extends Decoder <T > {
118+ const RecordDecoder (this .recordFactory);
119+
120+ /// A callback which returns a [Record] given the positional and named
121+ /// record fields.
122+ final RecordFactory <T > recordFactory;
123+
124+ @override
125+ /// Override this method and return a [Record] with shape [T] . <br/>
126+ /// Tip: Use the
127+ /// helper methods [positionalFields] and [namedFields] .
128+ T read (DartObject obj) {
129+ if (obj.type is RecordType ) {
130+ final recordObject = obj.toRecordValue ();
131+ return recordFactory (
132+ positional: recordObject? .positional ?? [],
133+ named: recordObject? .named ?? {},
134+ );
135+ } else {
136+ throw readError (obj);
137+ }
138+ }
139+
140+ static ErrorOf <RecordDecoder <T >> readRecordError <T extends Record >() =>
141+ ErrorOf <RecordDecoder <T >>(
142+ message: 'Could not read a record of type $T .' ,
143+ invalidState:
144+ 'The constant does seem to not represent a record with shape $T .' ,
145+ expectedState:
146+ 'The positional and named fields of the record and '
147+ 'their type must match $T . ' ,
148+ );
149+ }
0 commit comments