Unverified Commit 9c101515 authored by Martin Kustermann's avatar Martin Kustermann Committed by GitHub

Use utf8.encode() instead of longer const Utf8Encoder.convert() (#130567)

The change in [0] has propagated now everywhere, so we can use
`utf8.encode()` instead of the longer `const Utf8Encoder.convert()`.

Also it cleans up code like

```
  TypedData bytes;
  bytes.buffer.asByteData();
```

as that is not guaranteed to be correct, the correct version would be

```
  TypedData bytes;
  bytes.buffer.asByteData(bytes.offsetInBytes, bytes.lengthInBytes);
```

a shorter hand for that is:

```
  TypedData bytes;
  ByteData.sublistView(bytes);
```

[0] https://github.com/dart-lang/sdk/issues/52801
parent acdd96b2
...@@ -57,11 +57,10 @@ abstract class AssetBundle { ...@@ -57,11 +57,10 @@ abstract class AssetBundle {
/// Throws an exception if the asset is not found. /// Throws an exception if the asset is not found.
/// ///
/// The returned [ByteData] can be converted to a [Uint8List] (a list of bytes) /// The returned [ByteData] can be converted to a [Uint8List] (a list of bytes)
/// using [ByteData.buffer] to obtain a [ByteBuffer], and then /// using [Uint8List.sublistView]. Lists of bytes can be used with APIs that
/// [ByteBuffer.asUint8List] to obtain the byte list. Lists of bytes can be /// accept [Uint8List] objects, such as [decodeImageFromList], as well as any
/// used with APIs that accept [Uint8List] objects, such as /// API that accepts a [List<int>], such as [File.writeAsBytes] or
/// [decodeImageFromList], as well as any API that accepts a [List<int>], such /// [Utf8Codec.decode] (accessible via [utf8]).
/// as [File.writeAsBytes] or [Utf8Codec.decode] (accessible via [utf8]).
Future<ByteData> load(String key); Future<ByteData> load(String key);
/// Retrieve a binary resource from the asset bundle as an immutable /// Retrieve a binary resource from the asset bundle as an immutable
...@@ -70,7 +69,7 @@ abstract class AssetBundle { ...@@ -70,7 +69,7 @@ abstract class AssetBundle {
/// Throws an exception if the asset is not found. /// Throws an exception if the asset is not found.
Future<ui.ImmutableBuffer> loadBuffer(String key) async { Future<ui.ImmutableBuffer> loadBuffer(String key) async {
final ByteData data = await load(key); final ByteData data = await load(key);
return ui.ImmutableBuffer.fromUint8List(data.buffer.asUint8List()); return ui.ImmutableBuffer.fromUint8List(Uint8List.sublistView(data));
} }
/// Retrieve a string from the asset bundle. /// Retrieve a string from the asset bundle.
...@@ -91,7 +90,7 @@ abstract class AssetBundle { ...@@ -91,7 +90,7 @@ abstract class AssetBundle {
// 50 KB of data should take 2-3 ms to parse on a Moto G4, and about 400 μs // 50 KB of data should take 2-3 ms to parse on a Moto G4, and about 400 μs
// on a Pixel 4. // on a Pixel 4.
if (data.lengthInBytes < 50 * 1024) { if (data.lengthInBytes < 50 * 1024) {
return utf8.decode(data.buffer.asUint8List()); return utf8.decode(Uint8List.sublistView(data));
} }
// For strings larger than 50 KB, run the computation in an isolate to // For strings larger than 50 KB, run the computation in an isolate to
// avoid causing main thread jank. // avoid causing main thread jank.
...@@ -99,7 +98,7 @@ abstract class AssetBundle { ...@@ -99,7 +98,7 @@ abstract class AssetBundle {
} }
static String _utf8decode(ByteData data) { static String _utf8decode(ByteData data) {
return utf8.decode(data.buffer.asUint8List()); return utf8.decode(Uint8List.sublistView(data));
} }
/// Retrieve a string from the asset bundle, parse it with the given function, /// Retrieve a string from the asset bundle, parse it with the given function,
...@@ -161,7 +160,7 @@ class NetworkAssetBundle extends AssetBundle { ...@@ -161,7 +160,7 @@ class NetworkAssetBundle extends AssetBundle {
]); ]);
} }
final Uint8List bytes = await consolidateHttpClientResponseBytes(response); final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
return bytes.buffer.asByteData(); return ByteData.sublistView(bytes);
} }
// TODO(ianh): Once the underlying network logic learns about caching, we // TODO(ianh): Once the underlying network logic learns about caching, we
...@@ -308,7 +307,7 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -308,7 +307,7 @@ abstract class CachingAssetBundle extends AssetBundle {
@override @override
Future<ui.ImmutableBuffer> loadBuffer(String key) async { Future<ui.ImmutableBuffer> loadBuffer(String key) async {
final ByteData data = await load(key); final ByteData data = await load(key);
return ui.ImmutableBuffer.fromUint8List(data.buffer.asUint8List()); return ui.ImmutableBuffer.fromUint8List(Uint8List.sublistView(data));
} }
} }
...@@ -316,10 +315,10 @@ abstract class CachingAssetBundle extends AssetBundle { ...@@ -316,10 +315,10 @@ abstract class CachingAssetBundle extends AssetBundle {
class PlatformAssetBundle extends CachingAssetBundle { class PlatformAssetBundle extends CachingAssetBundle {
@override @override
Future<ByteData> load(String key) { Future<ByteData> load(String key) {
final Uint8List encoded = utf8.encoder.convert(Uri(path: Uri.encodeFull(key)).path); final Uint8List encoded = utf8.encode(Uri(path: Uri.encodeFull(key)).path);
final Future<ByteData>? future = ServicesBinding.instance.defaultBinaryMessenger.send( final Future<ByteData>? future = ServicesBinding.instance.defaultBinaryMessenger.send(
'flutter/assets', 'flutter/assets',
encoded.buffer.asByteData(), ByteData.sublistView(encoded),
)?.then((ByteData? asset) { )?.then((ByteData? asset) {
if (asset == null) { if (asset == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[ throw FlutterError.fromParts(<DiagnosticsNode>[
...@@ -342,7 +341,7 @@ class PlatformAssetBundle extends CachingAssetBundle { ...@@ -342,7 +341,7 @@ class PlatformAssetBundle extends CachingAssetBundle {
Future<ui.ImmutableBuffer> loadBuffer(String key) async { Future<ui.ImmutableBuffer> loadBuffer(String key) async {
if (kIsWeb) { if (kIsWeb) {
final ByteData bytes = await load(key); final ByteData bytes = await load(key);
return ui.ImmutableBuffer.fromUint8List(bytes.buffer.asUint8List()); return ui.ImmutableBuffer.fromUint8List(Uint8List.sublistView(bytes));
} }
bool debugUsePlatformChannel = false; bool debugUsePlatformChannel = false;
assert(() { assert(() {
...@@ -358,7 +357,7 @@ class PlatformAssetBundle extends CachingAssetBundle { ...@@ -358,7 +357,7 @@ class PlatformAssetBundle extends CachingAssetBundle {
}()); }());
if (debugUsePlatformChannel) { if (debugUsePlatformChannel) {
final ByteData bytes = await load(key); final ByteData bytes = await load(key);
return ui.ImmutableBuffer.fromUint8List(bytes.buffer.asUint8List()); return ui.ImmutableBuffer.fromUint8List(Uint8List.sublistView(bytes));
} }
try { try {
return await ui.ImmutableBuffer.fromAsset(key); return await ui.ImmutableBuffer.fromAsset(key);
......
...@@ -50,7 +50,7 @@ class StringCodec implements MessageCodec<String> { ...@@ -50,7 +50,7 @@ class StringCodec implements MessageCodec<String> {
if (message == null) { if (message == null) {
return null; return null;
} }
return utf8.decoder.convert(message.buffer.asUint8List(message.offsetInBytes, message.lengthInBytes)); return utf8.decode(Uint8List.sublistView(message));
} }
@override @override
...@@ -58,8 +58,7 @@ class StringCodec implements MessageCodec<String> { ...@@ -58,8 +58,7 @@ class StringCodec implements MessageCodec<String> {
if (message == null) { if (message == null) {
return null; return null;
} }
final Uint8List encoded = utf8.encoder.convert(message); return ByteData.sublistView(utf8.encode(message));
return encoded.buffer.asByteData();
} }
} }
...@@ -415,7 +414,7 @@ class StandardMessageCodec implements MessageCodec<Object?> { ...@@ -415,7 +414,7 @@ class StandardMessageCodec implements MessageCodec<Object?> {
if (char <= 0x7f) { if (char <= 0x7f) {
asciiBytes[i] = char; asciiBytes[i] = char;
} else { } else {
utf8Bytes = utf8.encoder.convert(value.substring(i)); utf8Bytes = utf8.encode(value.substring(i));
utf8Offset = i; utf8Offset = i;
break; break;
} }
......
...@@ -6176,7 +6176,7 @@ class RawImage extends LeafRenderObjectWidget { ...@@ -6176,7 +6176,7 @@ class RawImage extends LeafRenderObjectWidget {
/// @override /// @override
/// Future<ByteData> load(String key) async { /// Future<ByteData> load(String key) async {
/// if (key == 'resources/test') { /// if (key == 'resources/test') {
/// return ByteData.view(Uint8List.fromList(utf8.encode('Hello World!')).buffer); /// return ByteData.sublistView(utf8.encode('Hello World!'));
/// } /// }
/// return ByteData(0); /// return ByteData(0);
/// } /// }
......
...@@ -16,17 +16,16 @@ class TestAssetBundle extends CachingAssetBundle { ...@@ -16,17 +16,16 @@ class TestAssetBundle extends CachingAssetBundle {
Future<ByteData> load(String key) async { Future<ByteData> load(String key) async {
loadCallCount[key] = (loadCallCount[key] ?? 0) + 1; loadCallCount[key] = (loadCallCount[key] ?? 0) + 1;
if (key == 'AssetManifest.json') { if (key == 'AssetManifest.json') {
return ByteData.view(Uint8List.fromList(const Utf8Encoder().convert('{"one": ["one"]}')).buffer); return ByteData.sublistView(utf8.encode('{"one": ["one"]}'));
} }
if (key == 'AssetManifest.bin') { if (key == 'AssetManifest.bin') {
return const StandardMessageCodec().encodeMessage(<String, Object>{ return const StandardMessageCodec()
'one': <Object>[] .encodeMessage(<String, Object>{'one': <Object>[]})!;
})!;
} }
if (key == 'counter') { if (key == 'counter') {
return ByteData.view(Uint8List.fromList(const Utf8Encoder().convert(loadCallCount[key]!.toString())).buffer); return ByteData.sublistView(utf8.encode(loadCallCount[key]!.toString()));
} }
if (key == 'one') { if (key == 'one') {
......
...@@ -89,7 +89,7 @@ void main() { ...@@ -89,7 +89,7 @@ void main() {
int flutterAssetsCallCount = 0; int flutterAssetsCallCount = 0;
binding.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async { binding.defaultBinaryMessenger.setMockMessageHandler('flutter/assets', (ByteData? message) async {
flutterAssetsCallCount += 1; flutterAssetsCallCount += 1;
return Uint8List.fromList('test_asset_data'.codeUnits).buffer.asByteData(); return ByteData.sublistView(utf8.encode('test_asset_data'));
}); });
await rootBundle.loadString('test_asset'); await rootBundle.loadString('test_asset');
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
...@@ -14,15 +13,11 @@ class TestChannelBuffersFlutterBinding extends BindingBase with SchedulerBinding ...@@ -14,15 +13,11 @@ class TestChannelBuffersFlutterBinding extends BindingBase with SchedulerBinding
void main() { void main() {
ByteData makeByteData(String str) { ByteData makeByteData(String str) {
final List<int> list = utf8.encode(str); return ByteData.sublistView(utf8.encode(str));
final ByteBuffer buffer = list is Uint8List ? list.buffer : Uint8List.fromList(list).buffer;
return ByteData.view(buffer);
} }
String getString(ByteData data) { String getString(ByteData data) {
final ByteBuffer buffer = data.buffer; return utf8.decode(Uint8List.sublistView(data));
final List<int> list = buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
return utf8.decode(list);
} }
test('does drain channel buffers', () async { test('does drain channel buffers', () async {
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
...@@ -13,10 +12,7 @@ void main() { ...@@ -13,10 +12,7 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
ByteData makeByteData(String str) { ByteData makeByteData(String str) {
final List<int> list = utf8.encode(str); return ByteData.sublistView(utf8.encode(str));
final ByteBuffer buffer =
list is Uint8List ? list.buffer : Uint8List.fromList(list).buffer;
return ByteData.view(buffer);
} }
test('default binary messenger calls callback once', () async { test('default binary messenger calls callback once', () async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment