-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Did more investigating into multiple ways of using the Compression Streams API, and I realized that this is a really nice setup to have, possibly for a standalone module outside of NBTify. This provides a more cross-platform zlib API which would be similar to using `node:zlib`, but available both in the browser, and Node! It's build off of the Compression Streams API too, so it's only an API wrapper, and possibly a polyfill where necessary. I'm going to try settings things up first here, then move them to a dedicated project which both handles the compression polyfills, and provides these more functional-based APIs, which both provide more performance than my previous streams-specific `Blob` handling that I had before, and are simpler to use directly with `ArrayBuffer` and the various `TypedArray` objects, rather than having to go back and forth between `Blob` containers, which does appear to be a little less performant with the simple test that I set up. Oh my, that last sentence was horrible, I'm sorry. I guess I'm more of a dev than I am a writer. Offroaders123/Dovetail#1 whatwg/compression#8 https://wicg.github.io/compression/#example-deflate-compress https://jakearchibald.com/2017/async-iterators-and-generators/#making-streams-iterate
- Loading branch information
1 parent
5bcf05a
commit c3b5e95
Showing
6 changed files
with
104 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,71 @@ | ||
export type CompressionFormat = "gzip" | "deflate" | "deflate-raw"; | ||
|
||
export interface CompressionOptions { | ||
format: CompressionFormat; | ||
} | ||
|
||
/** | ||
* Compresses a Uint8Array using a specific compression format. | ||
*/ | ||
export async function compress(data: Uint8Array | ArrayBufferLike, { format }: CompressionOptions): Promise<Uint8Array> { | ||
const { body } = new Response(data instanceof Uint8Array ? data : new Uint8Array(data)); | ||
const readable = body!.pipeThrough(new CompressionStream(format)); | ||
const buffer = await new Response(readable).arrayBuffer(); | ||
return new Uint8Array(buffer); | ||
} | ||
|
||
/** | ||
* Decompresses a Uint8Array using a specific decompression format. | ||
*/ | ||
export async function decompress(data: Uint8Array | ArrayBufferLike, { format }: CompressionOptions): Promise<Uint8Array> { | ||
const { body } = new Response(data instanceof Uint8Array ? data : new Uint8Array(data)); | ||
const readable = body!.pipeThrough(new DecompressionStream(format)); | ||
const buffer = await new Response(readable).arrayBuffer(); | ||
return new Uint8Array(buffer); | ||
export async function gzip(data: BufferSource): Promise<Uint8Array> { | ||
return compress(data,"gzip"); | ||
} | ||
|
||
export async function gunzip(data: BufferSource): Promise<Uint8Array> { | ||
return decompress(data,"gzip"); | ||
} | ||
|
||
export async function deflate(data: BufferSource): Promise<Uint8Array> { | ||
return compress(data,"deflate"); | ||
} | ||
|
||
export async function inflate(data: BufferSource): Promise<Uint8Array> { | ||
return decompress(data,"deflate"); | ||
} | ||
|
||
export async function deflateRaw(data: BufferSource): Promise<Uint8Array> { | ||
return compress(data,"deflate-raw"); | ||
} | ||
|
||
export async function inflateRaw(data: BufferSource): Promise<Uint8Array> { | ||
return decompress(data,"deflate-raw"); | ||
} | ||
|
||
async function compress(data: BufferSource, format: CompressionFormat): Promise<Uint8Array> { | ||
const compressionStream = new CompressionStream(format); | ||
return pipeThroughCompressionStream(data,compressionStream); | ||
} | ||
|
||
async function decompress(data: BufferSource, format: CompressionFormat): Promise<Uint8Array> { | ||
const decompressionStream = new DecompressionStream(format); | ||
return pipeThroughCompressionStream(data,decompressionStream); | ||
} | ||
|
||
async function pipeThroughCompressionStream(data: BufferSource, compressionStream: CompressionStream | DecompressionStream): Promise<Uint8Array> { | ||
const writer = compressionStream.writable.getWriter(); | ||
|
||
writer.write(data); | ||
writer.close(); | ||
|
||
const chunks: Uint8Array[] = []; | ||
let byteLength = 0; | ||
|
||
for await (const chunk of readableStreamToAsyncGenerator(compressionStream.readable)){ | ||
chunks.push(chunk); | ||
byteLength += chunk.byteLength; | ||
} | ||
|
||
const result = new Uint8Array(byteLength); | ||
let byteOffset = 0; | ||
|
||
for (const chunk of chunks){ | ||
result.set(chunk,byteOffset); | ||
byteOffset += chunk.byteLength; | ||
} | ||
|
||
return result; | ||
} | ||
|
||
async function* readableStreamToAsyncGenerator(stream: ReadableStream<Uint8Array>): AsyncGenerator<Uint8Array,void,void> { | ||
const reader = stream.getReader(); | ||
try { | ||
while (true){ | ||
const { done, value } = await reader.read(); | ||
if (done) return; | ||
yield value; | ||
} | ||
} finally { | ||
reader.releaseLock(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import * as NBT from "../src/index.js"; | ||
|
||
interface TempTest { | ||
noice: NBT.BooleanTag; | ||
} | ||
|
||
const { data: tempTest } = new NBT.NBTData<TempTest>({ | ||
noice: true | ||
}); | ||
|
||
tempTest.noice | ||
// @ts-expect-error | ||
tempTest.notAProperty | ||
|
||
const demo = new NBT.NBTData({ nice: true, smartTypes: 10 }); | ||
|
||
demo.data.smartTypes; | ||
|
||
interface MyData { Version: boolean; } | ||
declare const heya: NBT.NBTData<MyData>; | ||
const noice = new NBT.NBTData(heya); | ||
|
||
const noice2 = await NBT.read(new Uint8Array(),heya); | ||
const noice3 = new NBT.NBTReader().read(new Uint8Array(),heya); |