transform<S> method

  1. @override
Stream<S> transform<S>(
  1. StreamTransformer<List<int>, S> streamTransformer
)
override

Applies streamTransformer to this stream.

Returns the transformed stream, that is, the result of streamTransformer.bind(this). This method simply allows writing the call to streamTransformer.bind in a chained fashion, like

stream.map(mapping).transform(transformation).toList()

which can be more convenient than calling bind directly.

The streamTransformer can return any stream. Whether the returned stream is a broadcast stream or not, and which elements it will contain, is entirely up to the transformation.

This method should always be used for transformations which treat the entire stream as representing a single value which has perhaps been split into several parts for transport, like a file being read from disk or being fetched over a network. The transformation will then produce a new stream which transforms the stream's value incrementally (perhaps using Converter.startChunkedConversion). The resulting stream may again be chunks of the result, but does not have to correspond to specific events from the source string.

Implementation

@override
Stream<S> transform<S>(StreamTransformer<List<int>, S> streamTransformer) {
  Stream<S> s = origin.transform<S>(streamTransformer);
  if (!isTextResponse()) {
    recordResponse(statusCode, '', headers, contentLength);
    return s;
  }
  s = s.asBroadcastStream();
  final stringChunks = <String>[];
  final byteChunks = <List<int>>[];
  s.listen((S event) {
    if (event is Uint8List) {
      byteChunks.add(event);
    } else if (event is String) {
      stringChunks.add(event);
    }
  }, onDone: () {
    if (stringChunks.isNotEmpty) {
      final joined = stringChunks.join();
      final actualSize =
          contentLength >= 0 ? contentLength : utf8.encode(joined).length;
      recordResponse(statusCode, joined, headers, actualSize);
    } else if (byteChunks.isNotEmpty) {
      final allBytes = byteChunks.expand((c) => c).toList();
      final actualSize = contentLength >= 0 ? contentLength : allBytes.length;
      var encoding = getEncoding();
      if (encoding != null) {
        String decodeResult = '';
        switch (encoding.runtimeType) {
          case Utf8Codec:
            decodeResult = utf8.decode(allBytes, allowMalformed: true);
            break;
          case Latin1Decoder:
            decodeResult = latin1.decode(allBytes, allowInvalid: true);
            break;
          case AsciiDecoder:
            decodeResult = ascii.decode(allBytes, allowInvalid: true);
            break;
          default:
            decodeResult = encoding.decode(allBytes);
        }
        recordResponse(statusCode, decodeResult, headers, actualSize);
      } else {
        recordResponse(statusCode, '返回结果解析失败', headers, actualSize);
      }
    } else {
      recordResponse(statusCode, '', headers, 0);
    }
  });
  return s;
}