1. はじめに
この節は参考情報です。
本仕様で定義されているAPIは、データストリームの圧縮および展開に使用されます。"deflate"、"deflate-raw"、"gzip"の各圧縮アルゴリズムをサポートしており、Web開発者に広く利用されています。
2. インフラストラクチャー
本仕様はInfraに依存しています。[INFRA]
チャンクとはデータの断片です。CompressionStreamおよびDecompressionStreamの場合、出力チャンクの型はUint8Arrayです。入力としては、任意のBufferSource
型を受け付けます。
ストリームは、順序付けられたチャンクの列を表します。ReadableStream
およびWritableStream
という用語はStreamsで定義されています。[STREAMS]
圧縮コンテキストとは、圧縮または展開アルゴリズムによって管理される内部状態のことです。圧縮コンテキストの内容は、使用するフォーマット・アルゴリズム・実装によって異なります。本仕様の観点からは、不透明なオブジェクトです。圧縮コンテキストは、最初は入力の最初のバイトを待ち受ける開始状態です。
3. 対応フォーマット
brotli-
「Brotli 圧縮データフォーマット」 [RFC7932]
-
実装は [RFC7932] 1.4節で説明されているとおり「準拠(compliant)」でなければなりません。
-
[RFC7932] 非準拠のブロックは
CompressionStreamによって作成されてはならず、DecompressionStreamにとってはエラーとなります。
-
deflate-
「ZLIB 圧縮データフォーマット」 [RFC1950]
注: このフォーマットは HTTP Content-Encodings との一貫性のために "deflate" と呼ばれています。[RFC7230] 4.2.2節参照。
-
実装は [RFC1950] 2.3節で説明されているとおり「準拠(compliant)」でなければなりません。
-
[RFC1950] で無効と記載されているフィールド値は、
CompressionStreamによって作成されてはならず、DecompressionStreamにとってはエラーとなります。 -
CMFフィールドのCM(圧縮方式) 部の唯一の有効値は 8 です。 -
FDICTフラグはこれらのAPIでサポートされておらず、設定されている場合はストリームはエラーとなります。 -
FLEVELフラグはDecompressionStreamにより無視されます。 -
ADLER32チェックサムが正しくない場合、DecompressionStreamはエラーとなります。 -
ADLER32チェックサム以降に入力データが存在する場合はエラーです。
-
deflate-raw-
「DEFLATE アルゴリズム」 [RFC1951]
-
実装は [RFC1951] 1.4節で説明されているとおり「準拠(compliant)」でなければなりません。
-
[RFC1951] 非準拠のブロックは
CompressionStreamによって作成されてはならず、DecompressionStreamにとってはエラーとなります。 -
BFINALフラグで示される最終ブロック以降に追加の入力データがある場合はエラーです。
-
gzip-
「GZIP ファイルフォーマット」 [RFC1952]
-
実装は [RFC1952] 2.3.1.2節で説明されているとおり「準拠(compliant)」でなければなりません。
-
[RFC1952] で無効と記載されているフィールド値は
CompressionStreamによって作成されてはならず、DecompressionStreamにとってはエラーとなります。 -
CM(圧縮方法) フィールドの唯一の有効値は 8 です。 -
FTEXTフラグはDecompressionStreamにより無視されなければなりません。 -
FHCRCフィールドが存在し、それが正しくない場合はエラーとなります。 -
全ての
FEXTRA,FNAME,FCOMMENTフィールドの内容はDecompressionStreamによって、正しく終了していることを検証する以外は無視しなければなりません。 -
MTIME,XFL,OS各フィールドの内容はDecompressionStreamにより無視されなければなりません。 -
CRC32またはISIZEが展開データと一致しない場合はエラーです。 -
gzipストリームには「メンバー」はひとつしか含まれてはなりません。 -
「メンバー」末尾以降に追加の入力データが存在する場合はエラーです。
-
4. インターフェース CompressionStream
enum {CompressionFormat ,"brotli" ,"deflate" ,"deflate-raw" , }; [Exposed=*]"gzip" interface {CompressionStream constructor (CompressionFormat ); };format CompressionStream includes GenericTransformStream ;
CompressionStream
には、関連付けられた format(フォーマット) および compression context(圧縮コンテキスト) context(コンテキスト)があります。
new CompressionStream(format)
の手順は以下の通りです:
-
もし format が
CompressionStreamでサポートされていなければ、TypeErrorをスローする。 -
transformAlgorithm を、chunk 引数を受け取り compress and enqueue a chunk(圧縮してチャンクをエンキュー)アルゴリズムを this と chunk で実行するアルゴリズムとする。
-
flushAlgorithm を、引数なしで compress flush and enqueue(圧縮してフラッシュ・エンキュー) アルゴリズムを this で実行するアルゴリズムとする。
-
this の transform を new
TransformStreamに設定する。 -
セットアップ を this の transform に対して、 transformAlgorithm を transformAlgorithm に、 flushAlgorithm を flushAlgorithm でセットする。
CompressionStream
オブジェクト cs と chunk を受けて次の手順を実行する:
-
もし chunk が
BufferSource型でなければ、TypeErrorをスローする。 -
もし buffer が空なら、returnする。
-
arrays を buffer をひとつまたは複数の非空の部分に分割し、それぞれを
Uint8Arrayに変換した結果とする。 -
各
Uint8Arrayarray を arrays から取り出して enqueue(エンキュー) し、 cs の transform に入れる。
ReadableStream
オブジェクトからデータの終端を扱うもので、CompressionStream
オブジェクト cs を受けて次の手順を実行する:
-
buffer を、空入力を cs の format と context で フィニッシュフラグ付きで圧縮した結果とする。
-
もし buffer が空なら、returnする。
-
arrays を buffer をひとつまたは複数の非空の部分に分割し、それぞれを
Uint8Arrayに変換した結果とする。 -
各
Uint8Arrayarray を arrays から取り出して enqueue(エンキュー) し、 cs の transform に入れる。
5. インターフェース DecompressionStream
[Exposed=*]interface {DecompressionStream constructor (CompressionFormat ); };format DecompressionStream includes GenericTransformStream ;
DecompressionStream
には、関連付けられた format(フォーマット) および compression context(圧縮コンテキスト) context(コンテキスト)があります。
new DecompressionStream(format)
の手順は以下の通りです:
-
もし format が
DecompressionStreamでサポートされていなければ、TypeErrorをスローする。 -
transformAlgorithm を、chunk 引数を受け取り decompress and enqueue a chunk(展開してチャンクをエンキュー)アルゴリズムを this と chunk で実行するアルゴリズムとする。
-
flushAlgorithm を、引数なしで decompress flush and enqueue(展開してフラッシュ・エンキュー) アルゴリズムを this で実行するアルゴリズムとする。
-
this の transform を new
TransformStreamに設定する。 -
セットアップ を this の transform に対して、 transformAlgorithm を transformAlgorithm に、 flushAlgorithm を flushAlgorithm でセットする。
DecompressionStream
オブジェクト ds と chunk を受けて次の手順を実行する:
-
もし chunk が
BufferSource型でなければ、TypeErrorをスローする。 -
buffer を ds の format と context で chunk を展開(デコード)した結果とする。もしこれによりエラーが発生した場合、
TypeErrorをスローする。 -
もし buffer が空なら、returnする。
-
arrays を buffer をひとつまたは複数の非空の部分に分割し、それぞれを
Uint8Arrayに変換した結果とする。 -
各
Uint8Arrayarray を arrays から取り出して enqueue(エンキュー) し、 ds の transform に入れる。 -
圧縮入力の終端に到達し、かつ ds の context が chunk を完全に消費していない場合は、
TypeErrorをスローする。
ReadableStream
オブジェクトからデータの終端を扱うもので、DecompressionStream
オブジェクト ds を受けて次の手順を実行する:
-
buffer を、空入力を ds の format と context で フィニッシュフラグ付きで展開(デコード)した結果とする。
-
もし buffer が空でない場合:
-
arrays を buffer をひとつまたは複数の非空の部分に分割し、それぞれを
Uint8Arrayに変換した結果とする。 -
各
Uint8Arrayarray を arrays から取り出して enqueue(エンキュー) し、 ds の transform に入れる。
-
-
圧縮入力の終端にまだ到達していない場合は、
TypeErrorをスローする。
6. プライバシーおよびセキュリティの考慮事項
このAPIはWebプラットフォームに新たな権限を追加しません。
ただし、攻撃者がデータの長さを取得できる場合、Web開発者は注意する必要があります。その場合、データの内容を推測される可能性があります。
7. 例
7.1. ストリームをGzip圧縮する
7.2. ArrayBufferをDeflate圧縮してUint8Arrayに変換
async function compressArrayBuffer( input) { const cs= new CompressionStream( 'deflate' ); const writer= cs. writable. getWriter(); writer. write( input); writer. close(); const output= []; let totalSize= 0 ; for ( const chunkof cs. readable) { output. push( value); totalSize+= value. byteLength; } const concatenated= new Uint8Array( totalSize); let offset= 0 ; for ( const arrayof output) { concatenated. set( array, offset); offset+= array. byteLength; } return concatenated; }
7.3. BlobをGzip展開してBlobに変換
function decompressBlob( blob) { const ds= new DecompressionStream( 'gzip' ); const decompressionStream= blob. stream(). pipeThrough( ds); return new Response( decompressionStream). blob(); }
謝辞
Canon Mukai、Domenic Denicola、そして平野豊に感謝します。この標準はAdam Rice(Google、ricea@chromium.org)によって執筆されました。
知的財産権
Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). この作業はクリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下で提供されます。その一部がソースコードに組み込まれている場合、ソースコード部分は代わりにBSD 3-Clause Licenseの下でライセンスされます。
これは現行標準です。 特許審査バージョンに関心のある方は、 現行標準審査ドラフトを参照してください。