Skip to content

Commit 6d3a3c3

Browse files
committed
Added RecordDecoder.
1 parent bd2146b commit 6d3a3c3

File tree

1 file changed

+58
-9
lines changed

1 file changed

+58
-9
lines changed

lib/src/decoder/core_decoder.dart

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import '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

35
import '../extension/type_methods.dart';
46
import 'decoder.dart';
@@ -12,8 +14,6 @@ class BoolDecoder extends Decoder<bool> {
1214
};
1315
}
1416

15-
const boolDecoder = BoolDecoder();
16-
1717
class 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-
5553
class 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-
6662
class 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-
7771
class 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
8996
class 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

Comments
 (0)