Merge branch 'master' into fix-47
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 35e0803..e3bd3c0 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -25,7 +25,7 @@
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1.0
with:
- channel: ${{ matrix.sdk }}
+ sdk: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
@@ -38,7 +38,7 @@
# Run tests on a matrix consisting of two dimensions:
# 1. OS: ubuntu-latest, (macos-latest, windows-latest)
- # 2. release channel: dev
+ # 2. release sdk: dev
test:
needs: analyze
runs-on: ${{ matrix.os }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e28c68e..797ea91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,11 @@
-## 3.0.1
+## 3.0.2
* Fix bug in `CodePage` class. See issue [#47](https://github.com/dart-lang/convert/issues/47).
+## 3.0.1
+
+* Dependency clean-up.
+
## 3.0.0
* Stable null safety release.
diff --git a/analysis_options.yaml b/analysis_options.yaml
index dcd46cb..85d6c12 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,13 +1,8 @@
-include: package:pedantic/analysis_options.yaml
+include: package:lints/recommended.yaml
analyzer:
strong-mode:
implicit-casts: false
- errors:
- # Ignore still failing lints from latest pkg:pedantic
- annotate_overrides: ignore
- prefer_single_quotes: ignore
-
linter:
rules:
- avoid_empty_else
diff --git a/lib/src/accumulator_sink.dart b/lib/src/accumulator_sink.dart
index d92b4a8..ef01a76 100644
--- a/lib/src/accumulator_sink.dart
+++ b/lib/src/accumulator_sink.dart
@@ -23,6 +23,7 @@
_events.clear();
}
+ @override
void add(T event) {
if (_isClosed) {
throw StateError("Can't add to a closed sink.");
@@ -31,6 +32,7 @@
_events.add(event);
}
+ @override
void close() {
_isClosed = true;
}
diff --git a/lib/src/byte_accumulator_sink.dart b/lib/src/byte_accumulator_sink.dart
index d1fab06..44cf178 100644
--- a/lib/src/byte_accumulator_sink.dart
+++ b/lib/src/byte_accumulator_sink.dart
@@ -30,14 +30,16 @@
_buffer.clear();
}
- void add(List<int> bytes) {
+ @override
+ void add(List<int> chunk) {
if (_isClosed) {
throw StateError("Can't add to a closed sink.");
}
- _buffer.addAll(bytes);
+ _buffer.addAll(chunk);
}
+ @override
void addSlice(List<int> chunk, int start, int end, bool isLast) {
if (_isClosed) {
throw StateError("Can't add to a closed sink.");
@@ -47,6 +49,7 @@
if (isLast) _isClosed = true;
}
+ @override
void close() {
_isClosed = true;
}
diff --git a/lib/src/codepage.dart b/lib/src/codepage.dart
index 296a116..cfc58db 100644
--- a/lib/src/codepage.dart
+++ b/lib/src/codepage.dart
@@ -162,7 +162,9 @@
/// A code page is a way to map bytes to character.
/// As such, it can only represent 256 different characters.
class CodePage extends Encoding {
+ @override
final CodePageDecoder decoder;
+ @override
final String name;
CodePageEncoder? _encoder;
@@ -213,13 +215,16 @@
int operator [](int byte) => decoder._char(byte);
/// Encodes [input] using `encoder.convert`.
+ @override
Uint8List encode(String input, {int? invalidCharacter}) =>
encoder.convert(input, invalidCharacter: invalidCharacter);
/// Decodes [bytes] using `encoder.convert`.
+ @override
String decode(List<int> bytes, {bool allowInvalid = false}) =>
decoder.convert(bytes, allowInvalid: allowInvalid);
+ @override
CodePageEncoder get encoder => _encoder ??= decoder._createEncoder();
}
@@ -237,6 +242,7 @@
/// or byte values not defined as a character in the code page,
/// are emitted as U+FFFD (the Unicode invalid character).
/// If not true, the bytes must be calid and defined characters.
+ @override
String convert(List<int> input, {bool allowInvalid = false});
CodePageEncoder _createEncoder();
@@ -277,6 +283,7 @@
_NonBmpCodePageDecoder(String characters) : this._(_buildMapping(characters));
_NonBmpCodePageDecoder._(this._characters);
+ @override
int _char(int byte) => _characters[byte];
static Uint32List _buildMapping(String characters) {
@@ -296,6 +303,7 @@
return result;
}
+ @override
CodePageEncoder _createEncoder() {
var result = <int, int>{};
for (var i = 0; i < 256; i++) {
@@ -307,6 +315,7 @@
return CodePageEncoder._(result);
}
+ @override
String convert(List<int> input, {bool allowInvalid = false}) {
var buffer = Uint32List(input.length);
for (var i = 0; i < input.length; i++) {
@@ -328,8 +337,10 @@
}
}
+ @override
int _char(int byte) => _characters.codeUnitAt(byte);
+ @override
String convert(List<int> bytes, {bool allowInvalid = false}) {
if (allowInvalid) return _convertAllowInvalid(bytes);
var count = bytes.length;
@@ -364,6 +375,7 @@
return String.fromCharCodes(codeUnits);
}
+ @override
CodePageEncoder _createEncoder() => CodePageEncoder._bmp(_characters);
}
@@ -396,6 +408,7 @@
/// If [input] contains characters that are not available
/// in this code page, they are replaced by the [invalidCharacter] byte,
/// and then [invalidCharacter] must have been supplied.
+ @override
Uint8List convert(String input, {int? invalidCharacter}) {
if (invalidCharacter != null) {
RangeError.checkValueInInterval(
diff --git a/lib/src/hex.dart b/lib/src/hex.dart
index 28e9203..9de28ed 100644
--- a/lib/src/hex.dart
+++ b/lib/src/hex.dart
@@ -22,7 +22,9 @@
///
/// This should be used via the [hex] field.
class HexCodec extends Codec<List<int>, String> {
+ @override
HexEncoder get encoder => hexEncoder;
+ @override
HexDecoder get decoder => hexDecoder;
const HexCodec._();
diff --git a/lib/src/hex/decoder.dart b/lib/src/hex/decoder.dart
index 9e3a122..0a65f45 100644
--- a/lib/src/hex/decoder.dart
+++ b/lib/src/hex/decoder.dart
@@ -20,17 +20,19 @@
class HexDecoder extends Converter<String, List<int>> {
const HexDecoder._();
- List<int> convert(String string) {
- if (!string.length.isEven) {
+ @override
+ List<int> convert(String input) {
+ if (!input.length.isEven) {
throw FormatException(
- "Invalid input length, must be even.", string, string.length);
+ "Invalid input length, must be even.", input, input.length);
}
- var bytes = Uint8List(string.length ~/ 2);
- _decode(string.codeUnits, 0, string.length, bytes, 0);
+ var bytes = Uint8List(input.length ~/ 2);
+ _decode(input.codeUnits, 0, input.length, bytes, 0);
return bytes;
}
+ @override
StringConversionSink startChunkedConversion(Sink<List<int>> sink) =>
_HexDecoderSink(sink);
}
@@ -49,6 +51,7 @@
_HexDecoderSink(this._sink);
+ @override
void addSlice(String string, int start, int end, bool isLast) {
RangeError.checkValidRange(start, end, string.length);
@@ -77,9 +80,11 @@
if (isLast) _close(string, end);
}
+ @override
ByteConversionSink asUtf8Sink(bool allowMalformed) =>
_HexDecoderByteSink(_sink);
+ @override
void close() => _close();
/// Like [close], but includes [string] and [index] in the [FormatException]
@@ -108,8 +113,10 @@
_HexDecoderByteSink(this._sink);
+ @override
void add(List<int> chunk) => addSlice(chunk, 0, chunk.length, false);
+ @override
void addSlice(List<int> chunk, int start, int end, bool isLast) {
RangeError.checkValidRange(start, end, chunk.length);
@@ -137,6 +144,7 @@
if (isLast) _close(chunk, end);
}
+ @override
void close() => _close();
/// Like [close], but includes [chunk] and [index] in the [FormatException]
diff --git a/lib/src/hex/encoder.dart b/lib/src/hex/encoder.dart
index 261a5d9..c45884f 100644
--- a/lib/src/hex/encoder.dart
+++ b/lib/src/hex/encoder.dart
@@ -19,8 +19,10 @@
class HexEncoder extends Converter<List<int>, String> {
const HexEncoder._();
- String convert(List<int> bytes) => _convert(bytes, 0, bytes.length);
+ @override
+ String convert(List<int> input) => _convert(input, 0, input.length);
+ @override
ByteConversionSink startChunkedConversion(Sink<String> sink) =>
_HexEncoderSink(sink);
}
@@ -32,16 +34,19 @@
_HexEncoderSink(this._sink);
+ @override
void add(List<int> chunk) {
_sink.add(_convert(chunk, 0, chunk.length));
}
+ @override
void addSlice(List<int> chunk, int start, int end, bool isLast) {
RangeError.checkValidRange(start, end, chunk.length);
_sink.add(_convert(chunk, start, end));
if (isLast) _sink.close();
}
+ @override
void close() {
_sink.close();
}
diff --git a/lib/src/identity_codec.dart b/lib/src/identity_codec.dart
index 9da7bca..2df6144 100644
--- a/lib/src/identity_codec.dart
+++ b/lib/src/identity_codec.dart
@@ -2,6 +2,7 @@
class _IdentityConverter<T> extends Converter<T, T> {
_IdentityConverter();
+ @override
T convert(T input) => input;
}
@@ -17,12 +18,15 @@
class IdentityCodec<T> extends Codec<T, T> {
const IdentityCodec();
+ @override
Converter<T, T> get decoder => _IdentityConverter<T>();
+ @override
Converter<T, T> get encoder => _IdentityConverter<T>();
/// Fuse with an other codec.
///
/// Fusing with the identify converter is a no-op, so this always return
/// [other].
+ @override
Codec<T, R> fuse<R>(Codec<T, R> other) => other;
}
diff --git a/lib/src/percent.dart b/lib/src/percent.dart
index b06d08f..4a2f377 100644
--- a/lib/src/percent.dart
+++ b/lib/src/percent.dart
@@ -31,7 +31,9 @@
/// interprets `+` as `0x2B` rather than `0x20` as emitted by
/// [Uri.encodeQueryComponent].
class PercentCodec extends Codec<List<int>, String> {
+ @override
PercentEncoder get encoder => percentEncoder;
+ @override
PercentDecoder get decoder => percentDecoder;
const PercentCodec._();
diff --git a/lib/src/percent/decoder.dart b/lib/src/percent/decoder.dart
index 456c888..d74ae9c 100644
--- a/lib/src/percent/decoder.dart
+++ b/lib/src/percent/decoder.dart
@@ -28,18 +28,20 @@
class PercentDecoder extends Converter<String, List<int>> {
const PercentDecoder._();
- List<int> convert(String string) {
+ @override
+ List<int> convert(String input) {
var buffer = Uint8Buffer();
- var lastDigit = _decode(string.codeUnits, 0, string.length, buffer);
+ var lastDigit = _decode(input.codeUnits, 0, input.length, buffer);
if (lastDigit != null) {
throw FormatException(
- "Input ended with incomplete encoded byte.", string, string.length);
+ "Input ended with incomplete encoded byte.", input, input.length);
}
return buffer.buffer.asUint8List(0, buffer.length);
}
+ @override
StringConversionSink startChunkedConversion(Sink<List<int>> sink) =>
_PercentDecoderSink(sink);
}
@@ -60,6 +62,7 @@
_PercentDecoderSink(this._sink);
+ @override
void addSlice(String string, int start, int end, bool isLast) {
RangeError.checkValidRange(start, end, string.length);
@@ -91,9 +94,11 @@
if (isLast) _close(string, end);
}
+ @override
ByteConversionSink asUtf8Sink(bool allowMalformed) =>
_PercentDecoderByteSink(_sink);
+ @override
void close() => _close();
/// Like [close], but includes [string] and [index] in the [FormatException]
@@ -124,8 +129,10 @@
_PercentDecoderByteSink(this._sink);
+ @override
void add(List<int> chunk) => addSlice(chunk, 0, chunk.length, false);
+ @override
void addSlice(List<int> chunk, int start, int end, bool isLast) {
RangeError.checkValidRange(start, end, chunk.length);
@@ -156,6 +163,7 @@
if (isLast) _close(chunk, end);
}
+ @override
void close() => _close();
/// Like [close], but includes [chunk] and [index] in the [FormatException]
diff --git a/lib/src/percent/encoder.dart b/lib/src/percent/encoder.dart
index a861468..7f14fc9 100644
--- a/lib/src/percent/encoder.dart
+++ b/lib/src/percent/encoder.dart
@@ -22,8 +22,10 @@
class PercentEncoder extends Converter<List<int>, String> {
const PercentEncoder._();
- String convert(List<int> bytes) => _convert(bytes, 0, bytes.length);
+ @override
+ String convert(List<int> input) => _convert(input, 0, input.length);
+ @override
ByteConversionSink startChunkedConversion(Sink<String> sink) =>
_PercentEncoderSink(sink);
}
@@ -35,16 +37,19 @@
_PercentEncoderSink(this._sink);
+ @override
void add(List<int> chunk) {
_sink.add(_convert(chunk, 0, chunk.length));
}
+ @override
void addSlice(List<int> chunk, int start, int end, bool isLast) {
RangeError.checkValidRange(start, end, chunk.length);
_sink.add(_convert(chunk, start, end));
if (isLast) _sink.close();
}
+ @override
void close() {
_sink.close();
}
diff --git a/lib/src/string_accumulator_sink.dart b/lib/src/string_accumulator_sink.dart
index c8bdf75..98b476e 100644
--- a/lib/src/string_accumulator_sink.dart
+++ b/lib/src/string_accumulator_sink.dart
@@ -23,23 +23,26 @@
_buffer.clear();
}
- void add(String chunk) {
+ @override
+ void add(String str) {
if (_isClosed) {
throw StateError("Can't add to a closed sink.");
}
- _buffer.write(chunk);
+ _buffer.write(str);
}
- void addSlice(String chunk, int start, int end, bool isLast) {
+ @override
+ void addSlice(String str, int start, int end, bool isLast) {
if (_isClosed) {
throw StateError("Can't add to a closed sink.");
}
- _buffer.write(chunk.substring(start, end));
+ _buffer.write(str.substring(start, end));
if (isLast) _isClosed = true;
}
+ @override
void close() {
_isClosed = true;
}
diff --git a/pubspec.yaml b/pubspec.yaml
index b31eef1..ad683ae 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,17 +1,16 @@
name: convert
-version: 3.0.1
+version: 3.0.2
description: >-
Utilities for converting between data representations.
Provides a number of Sink, Codec, Decoder, and Encoder types.
repository: https://github.com/dart-lang/convert
environment:
- sdk: '>=2.12.0-0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
typed_data: ^1.3.0
dev_dependencies:
- charcode: ^1.2.0
- pedantic: ^1.10.0
- test: ^1.16.0-nullsafety.9
+ lints: ^1.0.0
+ test: ^1.16.0
diff --git a/test/accumulator_sink_test.dart b/test/accumulator_sink_test.dart
index 2c280e1..1f0b204 100644
--- a/test/accumulator_sink_test.dart
+++ b/test/accumulator_sink_test.dart
@@ -6,7 +6,7 @@
import 'package:test/test.dart';
void main() {
- var sink;
+ late AccumulatorSink sink;
setUp(() {
sink = AccumulatorSink<int>();
});
@@ -25,13 +25,19 @@
});
test("clear() clears the events", () {
- sink..add(1)..add(2)..add(3);
+ sink
+ ..add(1)
+ ..add(2)
+ ..add(3);
expect(sink.events, equals([1, 2, 3]));
sink.clear();
expect(sink.events, isEmpty);
- sink..add(4)..add(5)..add(6);
+ sink
+ ..add(4)
+ ..add(5)
+ ..add(6);
expect(sink.events, equals([4, 5, 6]));
});
diff --git a/test/hex_test.dart b/test/hex_test.dart
index bbb1808..5e8fa28 100644
--- a/test/hex_test.dart
+++ b/test/hex_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:convert';
import 'package:convert/convert.dart';
import 'package:test/test.dart';
@@ -80,7 +81,7 @@
group("with chunked conversion", () {
late List<List<int>> results;
- var sink;
+ late StringConversionSink sink;
setUp(() {
results = [];
var controller = StreamController<List<int>>(sync: true);
diff --git a/test/percent_test.dart b/test/percent_test.dart
index 7a7bf81..9075ea1 100644
--- a/test/percent_test.dart
+++ b/test/percent_test.dart
@@ -3,103 +3,22 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:convert';
-import 'package:charcode/ascii.dart';
import 'package:convert/convert.dart';
import 'package:test/test.dart';
void main() {
group("encoder", () {
test("doesn't percent-encode unreserved characters", () {
- expect(
- percent.encode([
- $a,
- $b,
- $c,
- $d,
- $e,
- $f,
- $g,
- $h,
- $i,
- $j,
- $k,
- $l,
- $m,
- $n,
- $o,
- $p,
- $q,
- $r,
- $s,
- $t,
- $u,
- $v,
- $w,
- $x,
- $y,
- $z,
- $A,
- $B,
- $C,
- $D,
- $E,
- $F,
- $G,
- $H,
- $I,
- $J,
- $K,
- $L,
- $M,
- $N,
- $O,
- $P,
- $Q,
- $R,
- $S,
- $T,
- $U,
- $V,
- $W,
- $X,
- $Y,
- $Z,
- $0,
- $1,
- $2,
- $3,
- $4,
- $5,
- $6,
- $7,
- $8,
- $9,
- $dash,
- $dot,
- $underscore,
- $tilde
- ]),
- equals(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"));
+ var safeChars = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789-._~";
+ expect(percent.encode([...safeChars.codeUnits]), equals(safeChars));
});
test("percent-encodes reserved ASCII characters", () {
- expect(
- percent.encode([
- $space,
- $backquote,
- $open_brace,
- $at,
- $open_bracket,
- $comma,
- $division,
- $caret,
- $close_brace,
- $del,
- $nul,
- $percent
- ]),
+ expect(percent.encode([..." `{@[,/^}\x7f\x00%".codeUnits]),
equals("%20%60%7B%40%5B%2C%2F%5E%7D%7F%00%25"));
});
@@ -108,8 +27,7 @@
});
test("mixes encoded and unencoded characters", () {
- expect(
- percent.encode([$a, $plus, $b, $equal, 0x80]), equals("a%2Bb%3D%80"));
+ expect(percent.encode([..."a+b=\x80".codeUnits]), equals("a%2Bb%3D%80"));
});
group("with chunked conversion", () {
@@ -119,7 +37,7 @@
controller.stream.listen(results.add);
var sink = percent.encoder.startChunkedConversion(controller.sink);
- sink.add([$a, $plus, $b, $equal, 0x80]);
+ sink.add([..."a+b=\x80".codeUnits]);
expect(results, equals(["a%2Bb%3D%80"]));
sink.add([0x00, 0x01, 0xfe, 0xff]);
@@ -154,40 +72,26 @@
group("decoder", () {
test("converts percent-encoded strings to byte arrays", () {
- expect(percent.decode("a%2Bb%3D%801"),
- equals([$a, $plus, $b, $equal, 0x80, $1]));
+ expect(
+ percent.decode("a%2Bb%3D%801"), equals([..."a+b=\x801".codeUnits]));
});
test("supports lowercase letters", () {
- expect(
- percent.decode("a%2bb%3d%80"), equals([$a, $plus, $b, $equal, 0x80]));
+ expect(percent.decode("a%2bb%3d%80"), equals([..."a+b=\x80".codeUnits]));
});
test("supports more aggressive encoding", () {
- expect(percent.decode("%61%2E%5A"), equals([$a, $dot, $Z]));
+ expect(percent.decode("%61%2E%5A"), equals([..."a.Z".codeUnits]));
});
test("supports less aggressive encoding", () {
- expect(
- percent.decode(" `{@[,/^}\x7F\x00"),
- equals([
- $space,
- $backquote,
- $open_brace,
- $at,
- $open_bracket,
- $comma,
- $division,
- $caret,
- $close_brace,
- $del,
- $nul
- ]));
+ var chars = " `{@[,/^}\x7F\x00";
+ expect(percent.decode(chars), equals([...chars.codeUnits]));
});
group("with chunked conversion", () {
late List<List<int>> results;
- var sink;
+ late StringConversionSink sink;
setUp(() {
results = [];
var controller = StreamController<List<int>>(sync: true);
@@ -200,14 +104,14 @@
expect(
results,
equals([
- [$a, $plus, $b, $equal, 0x80, $1]
+ [..."a+b=\x801".codeUnits]
]));
sink.add("%00%01%FE%FF");
expect(
results,
equals([
- [$a, $plus, $b, $equal, 0x80, $1],
+ [..."a+b=\x801".codeUnits],
[0x00, 0x01, 0xfe, 0xff]
]));
});
@@ -217,31 +121,31 @@
expect(
results,
equals([
- [$a, $b]
+ [..."ab".codeUnits]
]));
sink.add("2");
expect(
results,
equals([
- [$a, $b]
+ [..."ab".codeUnits]
]));
sink.add("0cd%2");
expect(
results,
equals([
- [$a, $b],
- [$space, $c, $d]
+ [..."ab".codeUnits],
+ [..." cd".codeUnits]
]));
sink.add("0");
expect(
results,
equals(([
- [$a, $b],
- [$space, $c, $d],
- [$space]
+ [..."ab".codeUnits],
+ [..." cd".codeUnits],
+ [..." ".codeUnits]
])));
});
@@ -275,7 +179,7 @@
expect(
results,
equals([
- [$a, $b]
+ [..."ab".codeUnits]
]));
expect(() => sink.close(), throwsFormatException);
});
@@ -285,7 +189,7 @@
expect(
results,
equals([
- [$a, $b]
+ [..."ab".codeUnits]
]));
expect(() => sink.close(), throwsFormatException);
});
@@ -295,7 +199,7 @@
expect(
results,
equals([
- [$a, $b]
+ [..."ab".codeUnits]
]));
expect(() => sink.addSlice("ab%", 0, 3, true), throwsFormatException);
@@ -306,7 +210,7 @@
expect(
results,
equals([
- [$a, $b]
+ [..."ab".codeUnits]
]));
expect(() => sink.addSlice("ab%2", 0, 3, true), throwsFormatException);
diff --git a/test/string_accumulator_sink_test.dart b/test/string_accumulator_sink_test.dart
index 2bef19b..6c5b9fa 100644
--- a/test/string_accumulator_sink_test.dart
+++ b/test/string_accumulator_sink_test.dart
@@ -6,7 +6,7 @@
import 'package:test/test.dart';
void main() {
- var sink;
+ late StringAccumulatorSink sink;
setUp(() {
sink = StringAccumulatorSink();
});