Skip to content

Commit

Permalink
⚡ port JS String.prototype.slice() method to Dart
Browse files Browse the repository at this point in the history
  • Loading branch information
techouse committed Apr 15, 2024
1 parent 795c85d commit 6eaa49f
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 13 deletions.
13 changes: 6 additions & 7 deletions lib/src/extensions/decode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ extension _$Decode on QS {
key = options.decoder(part, charset: charset);
val = options.strictNullHandling ? null : '';
} else {
key = options.decoder(part.substring(0, pos), charset: charset);
key = options.decoder(part.slice(0, pos), charset: charset);
val = Utils.apply<dynamic>(
_parseArrayValue(part.substring(pos + 1), options),
_parseArrayValue(part.slice(pos + 1), options),
(dynamic val) => options.decoder(val, charset: charset),
);
}
Expand Down Expand Up @@ -109,7 +109,7 @@ extension _$Decode on QS {
} else {
obj = Map.of({});
final String cleanRoot = root.startsWith('[') && root.endsWith(']')
? root.substring(1, root.length - 1)
? root.slice(1, root.length - 1)
: root;
final String decodedRoot = options.decodeDotInKeys
? cleanRoot.replaceAll('%2E', '.')
Expand Down Expand Up @@ -163,8 +163,7 @@ extension _$Decode on QS {

// Get the parent
Match? segment = options.depth > 0 ? brackets.firstMatch(key) : null;
final String parent =
segment != null ? key.substring(0, segment.start) : key;
final String parent = segment != null ? key.slice(0, segment.start) : key;

// Stash the parent if it exists
final List<String> keys = [];
Expand All @@ -181,13 +180,13 @@ extension _$Decode on QS {
if (segment != null) {
keys.add(segment.group(1)!);
// Update the key to start searching from the next position
key = key.substring(segment.end);
key = key.slice(segment.end);
}
}

// If there's a remainder, just add whatever is left
if (segment != null) {
keys.add('[${key.substring(segment.start)}]');
keys.add('[${key.slice(segment.start)}]');
}

return _parseObject(keys, val, options, valuesParsed);
Expand Down
18 changes: 18 additions & 0 deletions lib/src/extensions/extensions.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:math' show min;
import 'package:qs_dart/src/models/undefined.dart';

extension IterableExtension<T> on Iterable<T> {
Expand All @@ -9,3 +10,20 @@ extension ListExtension<T> on List<T> {
/// Returns a new [List] without [Undefined] elements.
List<T> whereNotUndefined() => where((T el) => el is! Undefined).toList();
}

extension StringExtension on String {
/// Extracts a section of a string and returns a new string.
///
/// Modeled after JavaScript's `String.prototype.slice()` method.
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice
String slice(int start, [int? end]) {
end ??= length;
if (end < 0) {
end = length + end;
}
if (start < 0) {
start = length + start;
}
return substring(start, min(end, length));
}
}
1 change: 1 addition & 0 deletions lib/src/qs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:qs_dart/src/enums/duplicates.dart';
import 'package:qs_dart/src/enums/format.dart';
import 'package:qs_dart/src/enums/list_format.dart';
import 'package:qs_dart/src/enums/sentinel.dart';
import 'package:qs_dart/src/extensions/extensions.dart';
import 'package:qs_dart/src/models/decode_options.dart';
import 'package:qs_dart/src/models/encode_options.dart';
import 'package:qs_dart/src/models/undefined.dart';
Expand Down
10 changes: 4 additions & 6 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:collection' show SplayTreeMap;
import 'dart:convert' show latin1, utf8, Encoding;
import 'dart:math' show min;
import 'dart:typed_data' show ByteBuffer;

import 'package:collection/collection.dart' show MapEquality;
Expand Down Expand Up @@ -205,14 +204,14 @@ final class Utils {
if (c == 0x25) {
if (str[i + 1] == 'u') {
buffer.writeCharCode(
int.parse(str.substring(i + 2, i + 6), radix: 16),
int.parse(str.slice(i + 2, i + 6), radix: 16),
);
i += 6;
continue;
}

buffer.writeCharCode(
int.parse(str.substring(i + 1, i + 3), radix: 16),
int.parse(str.slice(i + 1, i + 3), radix: 16),
);
i += 3;
continue;
Expand Down Expand Up @@ -260,9 +259,8 @@ final class Utils {
final StringBuffer buffer = StringBuffer();

for (int j = 0; j < str!.length; j += _segmentLimit) {
final String segment = str.length >= _segmentLimit
? str.substring(j, min(j + _segmentLimit, str.length))
: str;
final String segment =
str.length >= _segmentLimit ? str.slice(j, j + _segmentLimit) : str;

for (int i = 0; i < segment.length; ++i) {
int c = segment.codeUnitAt(i);
Expand Down
11 changes: 11 additions & 0 deletions test/unit/extensions/extensions_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,15 @@ void main() {
expect(result, [1, 2, 4, 5]);
});
});

group('StringExtensions', () {
test('slice', () {
const String str = 'The quick brown fox jumps over the lazy dog.';
expect(str.slice(31), 'the lazy dog.');
expect(str.slice(31, 1999), 'the lazy dog.');
expect(str.slice(4, 19), 'quick brown fox');
expect(str.slice(-4), 'dog.');
expect(str.slice(-9, -5), 'lazy');
});
});
}

0 comments on commit 6eaa49f

Please sign in to comment.