Skip to content

Commit 85c184d

Browse files
committed
⚡ optimize encoding process by consolidating configuration handling in QS class
1 parent 27125a5 commit 85c184d

File tree

2 files changed

+29
-83
lines changed

2 files changed

+29
-83
lines changed

lib/src/extensions/encode.dart

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -35,70 +35,14 @@ extension _$Encode on QS {
3535
/// - [undefined]: Marks a *missing* value (e.g., absent map key). When `true`, nothing is emitted.
3636
/// - [sideChannel]: Active-path set used for cycle detection across traversal frames.
3737
/// - [prefix]: Root path seed used to initialize the first [KeyPathNode].
38-
/// If `addQueryPrefix` is true at the root, we start with `?`.
39-
/// - [generateArrayPrefix]: Strategy for array key generation (brackets/indices/repeat/comma).
40-
/// - [commaRoundTrip]: When true and a single-element list is encountered under `.comma`, emit `[]` to ensure the value round-trips back to an array.
41-
/// - [commaCompactNulls]: When true, nulls are omitted from `.comma` lists.
42-
/// - [allowEmptyLists]: If a list is empty, emit `key[]` instead of skipping.
43-
/// - [strictNullHandling]: If a present value is `null`, emit only the key (no `=`) instead of `key=`.
44-
/// - [skipNulls]: Skip keys whose value is `null`.
45-
/// - [encodeDotInKeys]: Replace literal `.` in keys with `%2E`.
46-
/// - [encoder]: Optional percent-encoder for values (and keys when `encodeValuesOnly == false`).
47-
/// - [serializeDate]: Optional serializer for `DateTime` → String *before* encoding.
48-
/// - [sort]: Optional comparator for determining key order at each object depth.
49-
/// - [filter]: Either a function `(key, value) → value` or an iterable that constrains emitted keys.
50-
/// - [allowDots]: When true, dot notation is used between path segments instead of brackets.
51-
/// - [format]: RFC3986 or RFC1738 — influences space/plus behavior via [formatter].
52-
/// - [formatter]: Converts scalar strings to their final on-wire form (applies percent-encoding).
53-
/// - [encodeValuesOnly]: When true, keys are left as-is and only values are encoded by [encoder].
54-
/// - [charset]: Present for parity; encoding is delegated to [encoder]/[formatter].
55-
/// - [addQueryPrefix]: At the root, prefix output with `?`.
38+
/// - [rootConfig]: Immutable encode options shared across traversal frames.
5639
static dynamic _encode(
5740
dynamic object, {
5841
required bool undefined,
5942
required Set<Object> sideChannel,
60-
String? prefix,
61-
ListFormatGenerator? generateArrayPrefix,
62-
bool? commaRoundTrip,
63-
bool commaCompactNulls = false,
64-
bool allowEmptyLists = false,
65-
bool strictNullHandling = false,
66-
bool skipNulls = false,
67-
bool encodeDotInKeys = false,
68-
Encoder? encoder,
69-
DateSerializer? serializeDate,
70-
Sorter? sort,
71-
dynamic filter,
72-
bool allowDots = false,
73-
Format format = Format.rfc3986,
74-
Formatter? formatter,
75-
bool encodeValuesOnly = false,
76-
Encoding charset = utf8,
77-
bool addQueryPrefix = false,
43+
required String prefix,
44+
required EncodeConfig rootConfig,
7845
}) {
79-
prefix ??= addQueryPrefix ? '?' : '';
80-
generateArrayPrefix ??= _indicesGenerator;
81-
commaRoundTrip ??= identical(generateArrayPrefix, _commaGenerator);
82-
formatter ??= format.formatter;
83-
final EncodeConfig rootConfig = EncodeConfig(
84-
generateArrayPrefix: generateArrayPrefix,
85-
commaRoundTrip: commaRoundTrip,
86-
commaCompactNulls: commaCompactNulls,
87-
allowEmptyLists: allowEmptyLists,
88-
strictNullHandling: strictNullHandling,
89-
skipNulls: skipNulls,
90-
encodeDotInKeys: encodeDotInKeys,
91-
encoder: encoder,
92-
serializeDate: serializeDate,
93-
sort: sort,
94-
filter: filter,
95-
allowDots: allowDots,
96-
format: format,
97-
formatter: formatter,
98-
encodeValuesOnly: encodeValuesOnly,
99-
charset: charset,
100-
);
101-
10246
List<String>? result;
10347
final List<EncodeFrame> stack = [
10448
EncodeFrame(

lib/src/qs.dart

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -140,41 +140,43 @@ final class QS {
140140

141141
// Active-path set used by the encoder for cycle detection across frames.
142142
final Set<Object> sideChannel = HashSet<Object>.identity();
143+
final ListFormatGenerator gen = options.listFormat.generator;
144+
final bool crt = identical(gen, ListFormat.comma.generator) &&
145+
options.commaRoundTrip == true;
146+
final bool ccn = identical(gen, ListFormat.comma.generator) &&
147+
options.commaCompactNulls == true;
148+
final EncodeConfig rootConfig = EncodeConfig(
149+
generateArrayPrefix: gen,
150+
commaRoundTrip: crt,
151+
commaCompactNulls: ccn,
152+
allowEmptyLists: options.allowEmptyLists,
153+
strictNullHandling: options.strictNullHandling,
154+
skipNulls: options.skipNulls,
155+
encodeDotInKeys: options.encodeDotInKeys,
156+
encoder: options.encode ? options.encoder : null,
157+
serializeDate: options.serializeDate,
158+
sort: options.sort,
159+
filter: options.filter,
160+
allowDots: options.allowDots,
161+
format: options.format,
162+
formatter: options.formatter,
163+
encodeValuesOnly: options.encodeValuesOnly,
164+
charset: options.charset,
165+
);
166+
143167
for (int i = 0; i < objKeys.length; i++) {
144168
final key = objKeys[i];
145169

146170
if (key is! String || (obj[key] == null && options.skipNulls)) {
147171
continue;
148172
}
149173

150-
final ListFormatGenerator gen = options.listFormat.generator;
151-
final bool crt = identical(gen, ListFormat.comma.generator) &&
152-
options.commaRoundTrip == true;
153-
final bool ccn = identical(gen, ListFormat.comma.generator) &&
154-
options.commaCompactNulls == true;
155-
156174
final encoded = _$Encode._encode(
157175
obj[key],
158176
undefined: !obj.containsKey(key),
159-
prefix: key,
160-
generateArrayPrefix: gen,
161-
commaRoundTrip: crt,
162-
commaCompactNulls: ccn,
163-
allowEmptyLists: options.allowEmptyLists,
164-
strictNullHandling: options.strictNullHandling,
165-
skipNulls: options.skipNulls,
166-
encodeDotInKeys: options.encodeDotInKeys,
167-
encoder: options.encode ? options.encoder : null,
168-
serializeDate: options.serializeDate,
169-
filter: options.filter,
170-
sort: options.sort,
171-
allowDots: options.allowDots,
172-
format: options.format,
173-
formatter: options.formatter,
174-
encodeValuesOnly: options.encodeValuesOnly,
175-
charset: options.charset,
176-
addQueryPrefix: options.addQueryPrefix,
177177
sideChannel: sideChannel,
178+
prefix: key,
179+
rootConfig: rootConfig,
178180
);
179181

180182
if (encoded is Iterable) {

0 commit comments

Comments
 (0)