|  | // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | part of dart.io; | 
|  |  | 
|  | /// Exposes ZLib options for input parameters. | 
|  | /// | 
|  | /// See http://www.zlib.net/manual.html for more documentation. | 
|  | abstract class ZLibOption { | 
|  | /// Minimal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits] | 
|  | /// and [ZLibDecoder.windowBits]. | 
|  | static const int minWindowBits = 8; | 
|  | @Deprecated("Use minWindowBits instead") | 
|  | static const int MIN_WINDOW_BITS = 8; | 
|  |  | 
|  | /// Maximal value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits] | 
|  | /// and [ZLibDecoder.windowBits]. | 
|  | static const int maxWindowBits = 15; | 
|  | @Deprecated("Use maxWindowBits instead") | 
|  | static const int MAX_WINDOW_BITS = 15; | 
|  |  | 
|  | /// Default value for [ZLibCodec.windowBits], [ZLibEncoder.windowBits] | 
|  | /// and [ZLibDecoder.windowBits]. | 
|  | static const int defaultWindowBits = 15; | 
|  | @Deprecated("Use defaultWindowBits instead") | 
|  | static const int DEFAULT_WINDOW_BITS = 15; | 
|  |  | 
|  | /// Minimal value for [ZLibCodec.level] and [ZLibEncoder.level]. | 
|  | static const int minLevel = -1; | 
|  | @Deprecated("Use minLevel instead") | 
|  | static const int MIN_LEVEL = -1; | 
|  |  | 
|  | /// Maximal value for [ZLibCodec.level] and [ZLibEncoder.level] | 
|  | static const int maxLevel = 9; | 
|  | @Deprecated("Use maxLevel instead") | 
|  | static const int MAX_LEVEL = 9; | 
|  |  | 
|  | /// Default value for [ZLibCodec.level] and [ZLibEncoder.level]. | 
|  | static const int defaultLevel = 6; | 
|  | @Deprecated("Use defaultLevel instead") | 
|  | static const int DEFAULT_LEVEL = 6; | 
|  |  | 
|  | /// Minimal value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel]. | 
|  | static const int minMemLevel = 1; | 
|  | @Deprecated("Use minMemLevel instead") | 
|  | static const int MIN_MEM_LEVEL = 1; | 
|  |  | 
|  | /// Maximal value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel]. | 
|  | static const int maxMemLevel = 9; | 
|  | @Deprecated("Use maxMemLevel instead") | 
|  | static const int MAX_MEM_LEVEL = 9; | 
|  |  | 
|  | /// Default value for [ZLibCodec.memLevel] and [ZLibEncoder.memLevel]. | 
|  | static const int defaultMemLevel = 8; | 
|  | @Deprecated("Use defaultMemLevel instead") | 
|  | static const int DEFAULT_MEM_LEVEL = 8; | 
|  |  | 
|  | /// Recommended strategy for data produced by a filter (or predictor) | 
|  | static const int strategyFiltered = 1; | 
|  | @Deprecated("Use strategyFiltered instead") | 
|  | static const int STRATEGY_FILTERED = 1; | 
|  |  | 
|  | /// Use this strategy to force Huffman encoding only (no string match) | 
|  | static const int strategyHuffmanOnly = 2; | 
|  | @Deprecated("Use strategyHuffmanOnly instead") | 
|  | static const int STRATEGY_HUFFMAN_ONLY = 2; | 
|  |  | 
|  | /// Use this strategy to limit match distances to one (run-length encoding) | 
|  | static const int strategyRle = 3; | 
|  | @Deprecated("Use strategyRle instead") | 
|  | static const int STRATEGY_RLE = 3; | 
|  |  | 
|  | /// This strategy prevents the use of dynamic Huffman codes, allowing for a | 
|  | /// simpler decoder | 
|  | static const int strategyFixed = 4; | 
|  | @Deprecated("Use strategyFixed instead") | 
|  | static const int STRATEGY_FIXED = 4; | 
|  |  | 
|  | /// Recommended strategy for normal data | 
|  | static const int strategyDefault = 0; | 
|  | @Deprecated("Use strategyDefault instead") | 
|  | static const int STRATEGY_DEFAULT = 0; | 
|  | } | 
|  |  | 
|  | /// An instance of the default implementation of the [ZLibCodec]. | 
|  | const ZLibCodec zlib = const ZLibCodec._default(); | 
|  | @Deprecated("Use zlib instead") | 
|  | const ZLibCodec ZLIB = zlib; | 
|  |  | 
|  | /// The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib | 
|  | /// compressed bytes to raw bytes. | 
|  | class ZLibCodec extends Codec<List<int>, List<int>> { | 
|  | /// When true, `GZip` frames will be added to the compressed data. | 
|  | final bool gzip; | 
|  |  | 
|  | /// The compression-[level] can be set in the range of `-1..9`, with `6` being | 
|  | /// the default compression level. Levels above `6` will have higher | 
|  | /// compression rates at the cost of more CPU and memory usage. Levels below | 
|  | /// `6` will use less CPU and memory at the cost of lower compression rates. | 
|  | final int level; | 
|  |  | 
|  | /// Specifies how much memory should be allocated for the internal compression | 
|  | /// state. `1` uses minimum memory but is slow and reduces compression ratio; | 
|  | /// `9` uses maximum memory for optimal speed. The default value is `8`. | 
|  | /// | 
|  | /// The memory requirements for deflate are (in bytes): | 
|  | /// ```dart | 
|  | /// (1 << (windowBits + 2)) +  (1 << (memLevel + 9)) | 
|  | /// ``` | 
|  | /// that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | 
|  | final int memLevel; | 
|  |  | 
|  | /// Tunes the compression algorithm. Use the value strategyDefault for normal | 
|  | /// data, strategyFiltered for data produced by a filter (or predictor), | 
|  | /// strategyHuffmanOnly to force Huffman encoding only (no string match), or | 
|  | /// strategyRle to limit match distances to one (run-length encoding). | 
|  | final int strategy; | 
|  |  | 
|  | /// Base two logarithm of the window size (the size of the history buffer). It | 
|  | /// should be in the range 8..15. Larger values result in better compression at | 
|  | /// the expense of memory usage. The default value is 15 | 
|  | final int windowBits; | 
|  |  | 
|  | /// When true, deflate generates raw data with no zlib header or trailer, and | 
|  | /// will not compute an adler32 check value | 
|  | final bool raw; | 
|  |  | 
|  | /// Initial compression dictionary. | 
|  | /// | 
|  | /// It should consist of strings (byte sequences) that are likely to be | 
|  | /// encountered later in the data to be compressed, with the most commonly used | 
|  | /// strings preferably put towards the end of the dictionary. Using a | 
|  | /// dictionary is most useful when the data to be compressed is short and can | 
|  | /// be predicted with good accuracy; the data can then be compressed better | 
|  | /// than with the default empty dictionary. | 
|  | final List<int>? dictionary; | 
|  |  | 
|  | ZLibCodec( | 
|  | {this.level = ZLibOption.defaultLevel, | 
|  | this.windowBits = ZLibOption.defaultWindowBits, | 
|  | this.memLevel = ZLibOption.defaultMemLevel, | 
|  | this.strategy = ZLibOption.strategyDefault, | 
|  | this.dictionary, | 
|  | this.raw = false, | 
|  | this.gzip = false}) { | 
|  | _validateZLibeLevel(level); | 
|  | _validateZLibMemLevel(memLevel); | 
|  | _validateZLibStrategy(strategy); | 
|  | _validateZLibWindowBits(windowBits); | 
|  | } | 
|  |  | 
|  | const ZLibCodec._default() | 
|  | : level = ZLibOption.defaultLevel, | 
|  | windowBits = ZLibOption.defaultWindowBits, | 
|  | memLevel = ZLibOption.defaultMemLevel, | 
|  | strategy = ZLibOption.strategyDefault, | 
|  | raw = false, | 
|  | gzip = false, | 
|  | dictionary = null; | 
|  |  | 
|  | /// Get a [ZLibEncoder] for encoding to `ZLib` compressed data. | 
|  | ZLibEncoder get encoder => new ZLibEncoder( | 
|  | gzip: false, | 
|  | level: level, | 
|  | windowBits: windowBits, | 
|  | memLevel: memLevel, | 
|  | strategy: strategy, | 
|  | dictionary: dictionary, | 
|  | raw: raw); | 
|  |  | 
|  | /// Get a [ZLibDecoder] for decoding `ZLib` compressed data. | 
|  | ZLibDecoder get decoder => | 
|  | new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw); | 
|  | } | 
|  |  | 
|  | /// An instance of the default implementation of the [GZipCodec]. | 
|  | const GZipCodec gzip = const GZipCodec._default(); | 
|  | @Deprecated("Use gzip instead") | 
|  | const GZipCodec GZIP = gzip; | 
|  |  | 
|  | /// The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip | 
|  | /// compressed bytes to raw bytes. | 
|  | /// | 
|  | /// The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec] | 
|  | /// wraps the `ZLib` compressed bytes in `GZip` frames. | 
|  | class GZipCodec extends Codec<List<int>, List<int>> { | 
|  | /// When true, `GZip` frames will be added to the compressed data. | 
|  | final bool gzip; | 
|  |  | 
|  | /// The compression-[level] can be set in the range of `-1..9`, with `6` being | 
|  | /// the default compression level. Levels above `6` will have higher | 
|  | /// compression rates at the cost of more CPU and memory usage. Levels below | 
|  | /// `6` will use less CPU and memory at the cost of lower compression rates. | 
|  | final int level; | 
|  |  | 
|  | /// Specifies how much memory should be allocated for the internal compression | 
|  | /// state. `1` uses minimum memory but is slow and reduces compression ratio; | 
|  | /// `9` uses maximum memory for optimal speed. The default value is `8`. | 
|  | /// | 
|  | /// The memory requirements for deflate are (in bytes): | 
|  | /// ```dart | 
|  | /// (1 << (windowBits + 2)) +  (1 << (memLevel + 9)) | 
|  | /// ``` | 
|  | /// that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | 
|  | final int memLevel; | 
|  |  | 
|  | /// Tunes the compression algorithm. Use the value | 
|  | /// [ZLibOption.strategyDefault] for normal data, | 
|  | /// [ZLibOption.strategyFiltered] for data produced by a filter | 
|  | /// (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman | 
|  | /// encoding only (no string match), or [ZLibOption.strategyRle] to limit | 
|  | /// match distances to one (run-length encoding). | 
|  | final int strategy; | 
|  |  | 
|  | /// Base two logarithm of the window size (the size of the history buffer). It | 
|  | /// should be in the range `8..15`. Larger values result in better compression | 
|  | /// at the expense of memory usage. The default value is `15` | 
|  | final int windowBits; | 
|  |  | 
|  | /// Initial compression dictionary. | 
|  | /// | 
|  | /// It should consist of strings (byte sequences) that are likely to be | 
|  | /// encountered later in the data to be compressed, with the most commonly used | 
|  | /// strings preferably put towards the end of the dictionary. Using a | 
|  | /// dictionary is most useful when the data to be compressed is short and can | 
|  | /// be predicted with good accuracy; the data can then be compressed better | 
|  | /// than with the default empty dictionary. | 
|  | final List<int>? dictionary; | 
|  |  | 
|  | /// When true, deflate generates raw data with no zlib header or trailer, and | 
|  | /// will not compute an adler32 check value | 
|  | final bool raw; | 
|  |  | 
|  | GZipCodec( | 
|  | {this.level = ZLibOption.defaultLevel, | 
|  | this.windowBits = ZLibOption.defaultWindowBits, | 
|  | this.memLevel = ZLibOption.defaultMemLevel, | 
|  | this.strategy = ZLibOption.strategyDefault, | 
|  | this.dictionary, | 
|  | this.raw = false, | 
|  | this.gzip = true}) { | 
|  | _validateZLibeLevel(level); | 
|  | _validateZLibMemLevel(memLevel); | 
|  | _validateZLibStrategy(strategy); | 
|  | _validateZLibWindowBits(windowBits); | 
|  | } | 
|  |  | 
|  | const GZipCodec._default() | 
|  | : level = ZLibOption.defaultLevel, | 
|  | windowBits = ZLibOption.defaultWindowBits, | 
|  | memLevel = ZLibOption.defaultMemLevel, | 
|  | strategy = ZLibOption.strategyDefault, | 
|  | raw = false, | 
|  | gzip = true, | 
|  | dictionary = null; | 
|  |  | 
|  | /// Get a [ZLibEncoder] for encoding to `GZip` compressed data. | 
|  | ZLibEncoder get encoder => new ZLibEncoder( | 
|  | gzip: true, | 
|  | level: level, | 
|  | windowBits: windowBits, | 
|  | memLevel: memLevel, | 
|  | strategy: strategy, | 
|  | dictionary: dictionary, | 
|  | raw: raw); | 
|  |  | 
|  | /// Get a [ZLibDecoder] for decoding `GZip` compressed data. | 
|  | ZLibDecoder get decoder => | 
|  | new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw); | 
|  | } | 
|  |  | 
|  | /// The [ZLibEncoder] encoder is used by [ZLibCodec] and [GZipCodec] to compress | 
|  | /// data. | 
|  | class ZLibEncoder extends Converter<List<int>, List<int>> { | 
|  | /// When true, `GZip` frames will be added to the compressed data. | 
|  | final bool gzip; | 
|  |  | 
|  | /// The compression-[level] can be set in the range of `-1..9`, with `6` being | 
|  | /// the default compression level. Levels above `6` will have higher | 
|  | /// compression rates at the cost of more CPU and memory usage. Levels below | 
|  | /// `6` will use less CPU and memory at the cost of lower compression rates. | 
|  | final int level; | 
|  |  | 
|  | /// Specifies how much memory should be allocated for the internal compression | 
|  | /// state. `1` uses minimum memory but is slow and reduces compression ratio; | 
|  | /// `9` uses maximum memory for optimal speed. The default value is `8`. | 
|  | /// | 
|  | /// The memory requirements for deflate are (in bytes): | 
|  | /// ```dart | 
|  | /// (1 << (windowBits + 2)) +  (1 << (memLevel + 9)) | 
|  | /// ``` | 
|  | /// that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | 
|  | final int memLevel; | 
|  |  | 
|  | /// Tunes the compression algorithm. Use the value | 
|  | /// [ZLibOption.strategyDefault] for normal data, | 
|  | /// [ZLibOption.strategyFiltered] for data produced by a filter | 
|  | /// (or predictor), [ZLibOption.strategyHuffmanOnly] to force Huffman | 
|  | /// encoding only (no string match), or [ZLibOption.strategyRle] to limit | 
|  | /// match distances to one (run-length encoding). | 
|  | final int strategy; | 
|  |  | 
|  | /// Base two logarithm of the window size (the size of the history buffer). It | 
|  | /// should be in the range `8..15`. Larger values result in better compression | 
|  | /// at the expense of memory usage. The default value is `15` | 
|  | final int windowBits; | 
|  |  | 
|  | /// Initial compression dictionary. | 
|  | /// | 
|  | /// It should consist of strings (byte sequences) that are likely to be | 
|  | /// encountered later in the data to be compressed, with the most commonly used | 
|  | /// strings preferably put towards the end of the dictionary. Using a | 
|  | /// dictionary is most useful when the data to be compressed is short and can | 
|  | /// be predicted with good accuracy; the data can then be compressed better | 
|  | /// than with the default empty dictionary. | 
|  | final List<int>? dictionary; | 
|  |  | 
|  | /// When true, deflate generates raw data with no zlib header or trailer, and | 
|  | /// will not compute an adler32 check value | 
|  | final bool raw; | 
|  |  | 
|  | ZLibEncoder( | 
|  | {this.gzip = false, | 
|  | this.level = ZLibOption.defaultLevel, | 
|  | this.windowBits = ZLibOption.defaultWindowBits, | 
|  | this.memLevel = ZLibOption.defaultMemLevel, | 
|  | this.strategy = ZLibOption.strategyDefault, | 
|  | this.dictionary, | 
|  | this.raw = false}) { | 
|  | _validateZLibeLevel(level); | 
|  | _validateZLibMemLevel(memLevel); | 
|  | _validateZLibStrategy(strategy); | 
|  | _validateZLibWindowBits(windowBits); | 
|  | } | 
|  |  | 
|  | /// Convert a list of bytes using the options given to the ZLibEncoder | 
|  | /// constructor. | 
|  | List<int> convert(List<int> bytes) { | 
|  | _BufferSink sink = new _BufferSink(); | 
|  | startChunkedConversion(sink) | 
|  | ..add(bytes) | 
|  | ..close(); | 
|  | return sink.builder.takeBytes(); | 
|  | } | 
|  |  | 
|  | /// Start a chunked conversion using the options given to the [ZLibEncoder] | 
|  | /// constructor. | 
|  | /// | 
|  | /// Accepts any `Sink<List<int>>`, but prefers a [ByteConversionSink], | 
|  | /// and converts any other sink to a [ByteConversionSink] before | 
|  | /// using it. | 
|  | ByteConversionSink startChunkedConversion(Sink<List<int>> sink) { | 
|  | if (sink is! ByteConversionSink) { | 
|  | sink = new ByteConversionSink.from(sink); | 
|  | } | 
|  | return new _ZLibEncoderSink._( | 
|  | sink, gzip, level, windowBits, memLevel, strategy, dictionary, raw); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// The [ZLibDecoder] is used by [ZLibCodec] and [GZipCodec] to decompress data. | 
|  | class ZLibDecoder extends Converter<List<int>, List<int>> { | 
|  | /// Base two logarithm of the window size (the size of the history buffer). It | 
|  | /// should be in the range `8..15`. Larger values result in better compression | 
|  | /// at the expense of memory usage. The default value is `15`. | 
|  | final int windowBits; | 
|  |  | 
|  | /// Initial compression dictionary. | 
|  | /// | 
|  | /// It should consist of strings (byte sequences) that are likely to be | 
|  | /// encountered later in the data to be compressed, with the most commonly used | 
|  | /// strings preferably put towards the end of the dictionary. Using a | 
|  | /// dictionary is most useful when the data to be compressed is short and can | 
|  | /// be predicted with good accuracy; the data can then be compressed better | 
|  | /// than with the default empty dictionary. | 
|  | final List<int>? dictionary; | 
|  |  | 
|  | /// When true, deflate generates raw data with no zlib header or trailer, and | 
|  | /// will not compute an adler32 check value | 
|  | final bool raw; | 
|  |  | 
|  | ZLibDecoder( | 
|  | {this.windowBits = ZLibOption.defaultWindowBits, | 
|  | this.dictionary, | 
|  | this.raw = false}) { | 
|  | _validateZLibWindowBits(windowBits); | 
|  | } | 
|  |  | 
|  | /// Convert a list of bytes using the options given to the [ZLibDecoder] | 
|  | /// constructor. | 
|  | List<int> convert(List<int> bytes) { | 
|  | _BufferSink sink = new _BufferSink(); | 
|  | startChunkedConversion(sink) | 
|  | ..add(bytes) | 
|  | ..close(); | 
|  | return sink.builder.takeBytes(); | 
|  | } | 
|  |  | 
|  | /// Start a chunked conversion. | 
|  | /// | 
|  | /// Accepts any `Sink<List<int>>`, but prefers a [ByteConversionSink], | 
|  | /// and converts any other sink to a [ByteConversionSink] before | 
|  | /// using it. | 
|  | ByteConversionSink startChunkedConversion(Sink<List<int>> sink) { | 
|  | if (sink is! ByteConversionSink) { | 
|  | sink = new ByteConversionSink.from(sink); | 
|  | } | 
|  | return new _ZLibDecoderSink._(sink, windowBits, dictionary, raw); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// The [RawZLibFilter] class provides a low-level interface to zlib. | 
|  | abstract class RawZLibFilter { | 
|  | /// Returns a a [RawZLibFilter] whose [process] and [processed] methods | 
|  | /// compress data. | 
|  | factory RawZLibFilter.deflateFilter({ | 
|  | bool gzip = false, | 
|  | int level = ZLibOption.defaultLevel, | 
|  | int windowBits = ZLibOption.defaultWindowBits, | 
|  | int memLevel = ZLibOption.defaultMemLevel, | 
|  | int strategy = ZLibOption.strategyDefault, | 
|  | List<int>? dictionary, | 
|  | bool raw = false, | 
|  | }) { | 
|  | return _makeZLibDeflateFilter( | 
|  | gzip, level, windowBits, memLevel, strategy, dictionary, raw); | 
|  | } | 
|  |  | 
|  | /// Returns a a [RawZLibFilter] whose [process] and [processed] methods | 
|  | /// decompress data. | 
|  | factory RawZLibFilter.inflateFilter({ | 
|  | int windowBits = ZLibOption.defaultWindowBits, | 
|  | List<int>? dictionary, | 
|  | bool raw = false, | 
|  | }) { | 
|  | return _makeZLibInflateFilter(windowBits, dictionary, raw); | 
|  | } | 
|  |  | 
|  | /// Process a chunk of data. | 
|  | /// | 
|  | /// This method must only be called when [processed] returns `null`. | 
|  | void process(List<int> data, int start, int end); | 
|  |  | 
|  | /// Get a chunk of processed data. | 
|  | /// | 
|  | /// When there are no more data available, [processed] will return `null`. | 
|  | /// Set [flush] to `false` for non-final calls | 
|  | /// to improve performance of some filters. | 
|  | /// | 
|  | /// The last call to [processed] should have [end] set to `true`. This will | 
|  | /// make sure an 'end' packet is written on the stream. | 
|  | // TODO: Which stream? | 
|  | List<int>? processed({bool flush = true, bool end = false}); | 
|  |  | 
|  | external static RawZLibFilter _makeZLibDeflateFilter( | 
|  | bool gzip, | 
|  | int level, | 
|  | int windowBits, | 
|  | int memLevel, | 
|  | int strategy, | 
|  | List<int>? dictionary, | 
|  | bool raw); | 
|  |  | 
|  | external static RawZLibFilter _makeZLibInflateFilter( | 
|  | int windowBits, List<int>? dictionary, bool raw); | 
|  | } | 
|  |  | 
|  | class _BufferSink extends ByteConversionSink { | 
|  | final BytesBuilder builder = new BytesBuilder(copy: false); | 
|  |  | 
|  | void add(List<int> chunk) { | 
|  | builder.add(chunk); | 
|  | } | 
|  |  | 
|  | void addSlice(List<int> chunk, int start, int end, bool isLast) { | 
|  | if (chunk is Uint8List) { | 
|  | Uint8List list = chunk; | 
|  | builder.add(new Uint8List.view( | 
|  | list.buffer, list.offsetInBytes + start, end - start)); | 
|  | } else { | 
|  | builder.add(chunk.sublist(start, end)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void close() {} | 
|  | } | 
|  |  | 
|  | class _ZLibEncoderSink extends _FilterSink { | 
|  | _ZLibEncoderSink._( | 
|  | ByteConversionSink sink, | 
|  | bool gzip, | 
|  | int level, | 
|  | int windowBits, | 
|  | int memLevel, | 
|  | int strategy, | 
|  | List<int>? dictionary, | 
|  | bool raw) | 
|  | : super( | 
|  | sink, | 
|  | RawZLibFilter._makeZLibDeflateFilter( | 
|  | gzip, level, windowBits, memLevel, strategy, dictionary, raw)); | 
|  | } | 
|  |  | 
|  | class _ZLibDecoderSink extends _FilterSink { | 
|  | _ZLibDecoderSink._( | 
|  | ByteConversionSink sink, int windowBits, List<int>? dictionary, bool raw) | 
|  | : super(sink, | 
|  | RawZLibFilter._makeZLibInflateFilter(windowBits, dictionary, raw)); | 
|  | } | 
|  |  | 
|  | class _FilterSink extends ByteConversionSink { | 
|  | final RawZLibFilter _filter; | 
|  | final ByteConversionSink _sink; | 
|  | bool _closed = false; | 
|  | bool _empty = true; | 
|  |  | 
|  | _FilterSink(this._sink, this._filter); | 
|  |  | 
|  | void add(List<int> data) { | 
|  | addSlice(data, 0, data.length, false); | 
|  | } | 
|  |  | 
|  | void addSlice(List<int> data, int start, int end, bool isLast) { | 
|  | // TODO(40614): Remove once non-nullability is sound. | 
|  | ArgumentError.checkNotNull(end, "end"); | 
|  | if (_closed) return; | 
|  | RangeError.checkValidRange(start, end, data.length); | 
|  | try { | 
|  | _empty = false; | 
|  | _BufferAndStart bufferAndStart = | 
|  | _ensureFastAndSerializableByteData(data, start, end); | 
|  | _filter.process(bufferAndStart.buffer, bufferAndStart.start, | 
|  | end - (start - bufferAndStart.start)); | 
|  | List<int>? out; | 
|  | while (true) { | 
|  | final out = _filter.processed(flush: false); | 
|  | if (out == null) break; | 
|  | _sink.add(out); | 
|  | } | 
|  | } catch (e) { | 
|  | _closed = true; | 
|  | rethrow; | 
|  | } | 
|  |  | 
|  | if (isLast) close(); | 
|  | } | 
|  |  | 
|  | void close() { | 
|  | if (_closed) return; | 
|  | // Be sure to send process an empty chunk of data. Without this, the empty | 
|  | // message would not have a GZip frame (if compressed with GZip). | 
|  | if (_empty) _filter.process(const [], 0, 0); | 
|  | try { | 
|  | while (true) { | 
|  | final out = _filter.processed(end: true); | 
|  | if (out == null) break; | 
|  | _sink.add(out); | 
|  | } | 
|  | } catch (e) { | 
|  | // TODO(kevmoo): not sure why this isn't a try/finally | 
|  | _closed = true; | 
|  | throw e; | 
|  | } | 
|  | _closed = true; | 
|  | _sink.close(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void _validateZLibWindowBits(int windowBits) { | 
|  | if (ZLibOption.minWindowBits > windowBits || | 
|  | ZLibOption.maxWindowBits < windowBits) { | 
|  | throw new RangeError.range( | 
|  | windowBits, ZLibOption.minWindowBits, ZLibOption.maxWindowBits); | 
|  | } | 
|  | } | 
|  |  | 
|  | void _validateZLibeLevel(int level) { | 
|  | if (ZLibOption.minLevel > level || ZLibOption.maxLevel < level) { | 
|  | throw new RangeError.range(level, ZLibOption.minLevel, ZLibOption.maxLevel); | 
|  | } | 
|  | } | 
|  |  | 
|  | void _validateZLibMemLevel(int memLevel) { | 
|  | if (ZLibOption.minMemLevel > memLevel || ZLibOption.maxMemLevel < memLevel) { | 
|  | throw new RangeError.range( | 
|  | memLevel, ZLibOption.minMemLevel, ZLibOption.maxMemLevel); | 
|  | } | 
|  | } | 
|  |  | 
|  | void _validateZLibStrategy(int strategy) { | 
|  | const strategies = const <int>[ | 
|  | ZLibOption.strategyFiltered, | 
|  | ZLibOption.strategyHuffmanOnly, | 
|  | ZLibOption.strategyRle, | 
|  | ZLibOption.strategyFixed, | 
|  | ZLibOption.strategyDefault | 
|  | ]; | 
|  | if (strategies.indexOf(strategy) == -1) { | 
|  | throw new ArgumentError("Unsupported 'strategy'"); | 
|  | } | 
|  | } |