Skip to content

Commit fd1a4cb

Browse files
committed
feat: make the API async
BREAKING CHANGE: API is now returning a promise
1 parent 9322e70 commit fd1a4cb

4 files changed

Lines changed: 58 additions & 34 deletions

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ import { fingerprintDiff } from 'mask-fingerprint'
6969

7070
const png = fs.readFileSync('diff.png')
7171

72-
const fingerprint = fingerprintDiff(png, {
72+
const fingerprint = await fingerprintDiff(png, {
7373
gridSize: 16,
7474
dilateRadius: 1,
7575
padToSquare: true,
@@ -92,6 +92,8 @@ The returned value is designed to be stored in a database, indexed, and compared
9292

9393
### `fingerprintDiff(buffer, options?)`
9494

95+
Returns a `Promise<string>`.
96+
9597
#### Parameters
9698

9799
**buffer**

__test__/index.spec.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,32 @@ import { describe, expect, it } from 'vitest'
55
import { fingerprintDiff } from '../index'
66

77
describe('diff fingerprint', () => {
8-
it('generates a same fingerprint for similar diffs', () => {
8+
it('generates a same fingerprint for similar diffs', async () => {
99
const fixturesDir = path.join(__dirname, './__fixtures__')
1010

11-
const generateFingerprintFromFilename = (name: string) => {
11+
const generateFingerprintFromFilename = async (name: string) => {
1212
const diffPath = path.join(fixturesDir, name)
1313
const buffer = fs.readFileSync(diffPath)
1414
console.time(name)
15-
const res = fingerprintDiff(buffer)
15+
const res = await fingerprintDiff(buffer)
1616
console.timeEnd(name)
1717
return res
1818
}
1919

20-
const generateFingerprintFromPath = (name: string) => {
20+
const generateFingerprintFromPath = async (name: string) => {
2121
const diffPath = path.join(fixturesDir, name)
2222
console.time(`${name}-path`)
23-
const res = fingerprintDiff(diffPath)
23+
const res = await fingerprintDiff(diffPath)
2424
console.timeEnd(`${name}-path`)
2525
return res
2626
}
2727

28-
const fA1 = generateFingerprintFromFilename('diff-A1.png')
29-
const fA1Path = generateFingerprintFromPath('diff-A1.png')
30-
const fA2 = generateFingerprintFromFilename('diff-A2.png')
31-
const fA3 = generateFingerprintFromFilename('diff-A3.png')
32-
const fB1 = generateFingerprintFromFilename('diff-B1.png')
33-
const fLong = generateFingerprintFromFilename('long-diff.png')
28+
const fA1 = await generateFingerprintFromFilename('diff-A1.png')
29+
const fA1Path = await generateFingerprintFromPath('diff-A1.png')
30+
const fA2 = await generateFingerprintFromFilename('diff-A2.png')
31+
const fA3 = await generateFingerprintFromFilename('diff-A3.png')
32+
const fB1 = await generateFingerprintFromFilename('diff-B1.png')
33+
const fLong = await generateFingerprintFromFilename('long-diff.png')
3434

3535
expect(fA1).toBe('v1:g16:d1:t0.002,0.02,0.08:202566ca9533046b')
3636
expect(fA1).toBe(fA2)

index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* auto-generated by NAPI-RS */
22
/* eslint-disable */
3-
export declare function fingerprintDiff(pngInput: string | Buffer, options?: JsEqualityFingerprintOptions | undefined | null): string
3+
export declare function fingerprintDiff(pngInput: string | Buffer, options?: JsEqualityFingerprintOptions | undefined | null): Promise<unknown>
44

55
export interface JsEqualityFingerprintOptions {
66
redThreshold?: JsRedThreshold

src/lib.rs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![deny(clippy::all)]
22

3-
use napi::bindgen_prelude::{Buffer, Either};
3+
use napi::{Env, Task};
4+
use napi::bindgen_prelude::{AsyncTask, Buffer, Either};
45
use napi_derive::napi;
56
use std::io::{BufReader, Cursor};
67

@@ -141,33 +142,54 @@ fn clamp_u32_to_u8(v: u32) -> u8 {
141142

142143
/* ---------------------------------- NAPI ---------------------------------- */
143144

145+
enum InputBytes {
146+
Path(String),
147+
Bytes(Vec<u8>),
148+
}
149+
150+
pub struct FingerprintDiffTask {
151+
input: InputBytes,
152+
options: Option<JsEqualityFingerprintOptions>,
153+
}
154+
155+
impl Task for FingerprintDiffTask {
156+
type Output = String;
157+
type JsValue = String;
158+
159+
fn compute(&mut self) -> napi::Result<Self::Output> {
160+
let opts = build_options(self.options.take())?;
161+
162+
match &self.input {
163+
InputBytes::Path(path) => {
164+
let png_bytes = std::fs::read(path).map_err(|e| {
165+
napi::Error::from_reason(format!("Failed to read PNG file '{path}': {e}"))
166+
})?;
167+
let (rgba, width, height) = decode_png_to_rgba(&png_bytes)?;
168+
Ok(fingerprint_rgba_for_equality(&rgba, width, height, &opts))
169+
}
170+
InputBytes::Bytes(png_bytes) => {
171+
let (rgba, width, height) = decode_png_to_rgba(png_bytes)?;
172+
Ok(fingerprint_rgba_for_equality(&rgba, width, height, &opts))
173+
}
174+
}
175+
}
176+
177+
fn resolve(&mut self, _env: Env, output: Self::Output) -> napi::Result<Self::JsValue> {
178+
Ok(output)
179+
}
180+
}
181+
144182
#[napi]
145183
pub fn fingerprint_diff(
146184
png_input: Either<String, Buffer>,
147185
options: Option<JsEqualityFingerprintOptions>,
148-
) -> napi::Result<String> {
149-
enum InputBytes {
150-
File(Vec<u8>),
151-
Buffer(Buffer),
152-
}
153-
186+
) -> napi::Result<AsyncTask<FingerprintDiffTask>> {
154187
let input = match png_input {
155-
Either::A(path) => {
156-
let bytes = std::fs::read(&path)
157-
.map_err(|e| napi::Error::from_reason(format!("Failed to read PNG file '{path}': {e}")))?;
158-
InputBytes::File(bytes)
159-
}
160-
Either::B(buffer) => InputBytes::Buffer(buffer),
161-
};
162-
163-
let png_bytes: &[u8] = match &input {
164-
InputBytes::File(bytes) => bytes.as_slice(),
165-
InputBytes::Buffer(buffer) => buffer.as_ref(),
188+
Either::A(path) => InputBytes::Path(path),
189+
Either::B(buffer) => InputBytes::Bytes(buffer.to_vec()),
166190
};
167191

168-
let (rgba, width, height) = decode_png_to_rgba(png_bytes)?;
169-
let opts = build_options(options)?;
170-
Ok(fingerprint_rgba_for_equality(&rgba, width, height, &opts))
192+
Ok(AsyncTask::new(FingerprintDiffTask { input, options }))
171193
}
172194

173195
/* -------------------------------- PNG decode -------------------------------- */

0 commit comments

Comments
 (0)