Skip to content

Commit

Permalink
feat: provide copyOutputData to compatible with electron >= 21
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Oct 2, 2022
1 parent 749bebb commit 777841d
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 49 deletions.
13 changes: 13 additions & 0 deletions __test__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@ test('should be able to compress Buffer', (t) => {
t.deepEqual(compressSync(fixture), Buffer.from([11, 40, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]))
})

test('should be able to compress Buffer with copied option', (t) => {
const fixture = 'hello world'
t.deepEqual(
compressSync(fixture, { copyOutputData: true }),
Buffer.from([11, 40, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]),
)
})

test('compress should be async version of compressSync', async (t) => {
const fixture = 'hello world 😂 🎧 🚀'
t.deepEqual(await compress(fixture), compressSync(fixture))
})

test('should be able to compress with copyOutputData', async (t) => {
const fixture = 'hello world 😂 🎧 🚀'
t.deepEqual(await compress(fixture, { copyOutputData: true }), compressSync(fixture))
})

test('should be able to uncompress sync', (t) => {
const fixture = 'hello world 😂 🎧 🚀'
t.deepEqual(uncompressSync(compressSync(fixture)), Buffer.from(fixture))
Expand Down
32 changes: 27 additions & 5 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,32 @@

/* auto-generated by NAPI-RS */

export interface Options {
export interface DecOptions {
asBuffer?: boolean
/**
* do not use `create_external_buffer` to create the output buffer
* set this option to `true` will make the API slower
* for compatibility with electron >= 21
* see https://www.electronjs.org/blog/v8-memory-cage and https://github.com/electron/electron/issues/35801#issuecomment-1261206333
*/
copyOutputData?: boolean
}
export function compressSync(input: Buffer | string): Buffer
export function compress(input: string | Buffer, signal?: AbortSignal | undefined | null): Promise<Buffer>
export function uncompressSync(input: string | Buffer, asBuffer?: Options | undefined | null): string | Buffer
export function uncompress(input: string | Buffer, options?: Options | undefined | null, signal?: AbortSignal | undefined | null): Promise<string | Buffer>
export interface EncOptions {
/**
* do not use `create_external_buffer` to create the output buffer
* for compatibility with electron >= 21
* set this option to `true` will make the API slower
* see https://www.electronjs.org/blog/v8-memory-cage and https://github.com/electron/electron/issues/35801#issuecomment-1261206333
*/
copyOutputData?: boolean
}
export function compressSync(input: string | Buffer, options?: EncOptions | undefined | null): Buffer
export function compress(input: string | Buffer, options?: EncOptions | undefined | null, signal?: AbortSignal | undefined | null): Promise<Buffer>
export function uncompressSync(input: string | Buffer, options?: DecOptions | undefined | null): string | Buffer
export function uncompress(input: string | Buffer, options?: DecOptions | undefined | null, signal?: AbortSignal | undefined | null): Promise<string | Buffer>
119 changes: 75 additions & 44 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,22 @@ pub enum Data {
}

#[napi(object)]
pub struct Options {
pub struct DecOptions {
pub as_buffer: Option<bool>,
/// do not use `create_external_buffer` to create the output buffer \n
/// set this option to `true` will make the API slower \n
/// for compatibility with electron >= 21 \n
/// see https://www.electronjs.org/blog/v8-memory-cage and https://github.com/electron/electron/issues/35801#issuecomment-1261206333
pub copy_output_data: Option<bool>,
}

#[napi(object)]
pub struct EncOptions {
/// do not use `create_external_buffer` to create the output buffer \n
/// for compatibility with electron >= 21 \n
/// set this option to `true` will make the API slower \n
/// see https://www.electronjs.org/blog/v8-memory-cage and https://github.com/electron/electron/issues/35801#issuecomment-1261206333
pub copy_output_data: Option<bool>,
}

impl TryFrom<Either<String, JsBuffer>> for Data {
Expand All @@ -34,9 +48,10 @@ impl TryFrom<Either<String, JsBuffer>> for Data {
}
}

struct Enc {
pub struct Enc {
inner: Encoder,
data: Data,
options: Option<EncOptions>,
}

#[napi]
Expand All @@ -55,7 +70,17 @@ impl Task for Enc {
}

fn resolve(&mut self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
env.create_buffer_with_data(output).map(|b| b.into_raw())
if self
.options
.as_ref()
.and_then(|o| o.copy_output_data)
.unwrap_or(false)
{
env.create_buffer_copy(output)
} else {
env.create_buffer_with_data(output)
}
.map(|b| b.into_raw())
}

fn finally(&mut self, env: Env) -> Result<()> {
Expand All @@ -66,16 +91,16 @@ impl Task for Enc {
}
}

struct Dec {
pub struct Dec {
inner: Decoder,
data: Data,
as_buffer: bool,
options: Option<DecOptions>,
}

#[napi]
impl Task for Dec {
type Output = Vec<u8>;
type JsValue = Either<String, Buffer>;
type JsValue = Either<String, JsBuffer>;

fn compute(&mut self) -> Result<Self::Output> {
self
Expand All @@ -87,9 +112,18 @@ impl Task for Dec {
.map_err(|e| Error::new(Status::GenericFailure, format!("{}", e)))
}

fn resolve(&mut self, _env: Env, output: Self::Output) -> Result<Self::JsValue> {
if self.as_buffer {
Ok(Either::B(output.into()))
fn resolve(&mut self, env: Env, output: Self::Output) -> Result<Self::JsValue> {
let opt_ref = self.options.as_ref();
if opt_ref.and_then(|o| o.as_buffer).unwrap_or(true) {
if opt_ref.and_then(|o| o.copy_output_data).unwrap_or(false) {
Ok(Either::B(
env.create_buffer_copy(output).map(|o| o.into_raw())?,
))
} else {
Ok(Either::B(
env.create_buffer_with_data(output).map(|o| o.into_raw())?,
))
}
} else {
Ok(Either::A(String::from_utf8(output).map_err(|e| {
Error::new(Status::GenericFailure, format!("{}", e))
Expand All @@ -106,26 +140,32 @@ impl Task for Dec {
}

#[napi]
pub fn compress_sync(input: Either<Buffer, String>) -> Result<Buffer> {
let mut enc = Encoder::new();
enc
.compress_vec(match input {
Either::A(ref b) => b.as_ref(),
Either::B(ref s) => s.as_bytes(),
})
.map_err(|e| Error::new(napi::Status::GenericFailure, format!("{}", e)))
.map(|v| v.into())
pub fn compress_sync(
env: Env,
input: Either<String, JsBuffer>,
options: Option<EncOptions>,
) -> Result<JsBuffer> {
let enc = Encoder::new();
let mut encoder = Enc {
inner: enc,
data: Data::try_from(input)?,
options: options,
};
let output = encoder.compute()?;
encoder.resolve(env, output)
}

#[napi]
fn compress(
pub fn compress(
input: Either<String, JsBuffer>,
options: Option<EncOptions>,
signal: Option<AbortSignal>,
) -> Result<AsyncTask<Enc>> {
let enc = Encoder::new();
let encoder = Enc {
inner: enc,
data: Data::try_from(input)?,
options: options,
};
match signal {
Some(s) => Ok(AsyncTask::with_signal(encoder, s)),
Expand All @@ -134,41 +174,32 @@ fn compress(
}

#[napi]
fn uncompress_sync(
input: Either<String, Buffer>,
as_buffer: Option<Options>,
) -> Result<Either<String, Buffer>> {
let as_buffer = as_buffer.and_then(|o| o.as_buffer).unwrap_or(true);
let mut dec = Decoder::new();
dec
.decompress_vec(match input {
Either::A(ref s) => s.as_bytes(),
Either::B(ref b) => b.as_ref(),
})
.map_err(|e| Error::new(napi::Status::GenericFailure, format!("{}", e)))
.and_then(|d| {
if as_buffer {
Ok(Either::B(d.into()))
} else {
Ok(Either::A(String::from_utf8(d).map_err(|e| {
Error::new(Status::GenericFailure, format!("{}", e))
})?))
}
})
pub fn uncompress_sync(
env: Env,
input: Either<String, JsBuffer>,
options: Option<DecOptions>,
) -> Result<Either<String, JsBuffer>> {
let dec = Decoder::new();
let mut decoder = Dec {
inner: dec,
data: Data::try_from(input)?,
options,
};
let output = decoder.compute()?;
decoder.resolve(env, output)
}

#[napi]
fn uncompress(
pub fn uncompress(
input: Either<String, JsBuffer>,
options: Option<Options>,
options: Option<DecOptions>,
signal: Option<AbortSignal>,
) -> Result<AsyncTask<Dec>> {
let as_buffer = options.and_then(|o| o.as_buffer).unwrap_or(true);
let dec = Decoder::new();
let decoder = Dec {
inner: dec,
data: Data::try_from(input)?,
as_buffer,
options,
};
match signal {
Some(s) => Ok(AsyncTask::with_signal(decoder, s)),
Expand Down

0 comments on commit 777841d

Please sign in to comment.