|
1 | 1 | #![deny(clippy::all)] |
2 | 2 |
|
3 | | -use napi::bindgen_prelude::{Buffer, Either}; |
| 3 | +use napi::{Env, Task}; |
| 4 | +use napi::bindgen_prelude::{AsyncTask, Buffer, Either}; |
4 | 5 | use napi_derive::napi; |
5 | 6 | use std::io::{BufReader, Cursor}; |
6 | 7 |
|
@@ -141,33 +142,54 @@ fn clamp_u32_to_u8(v: u32) -> u8 { |
141 | 142 |
|
142 | 143 | /* ---------------------------------- NAPI ---------------------------------- */ |
143 | 144 |
|
| 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 | + |
144 | 182 | #[napi] |
145 | 183 | pub fn fingerprint_diff( |
146 | 184 | png_input: Either<String, Buffer>, |
147 | 185 | options: Option<JsEqualityFingerprintOptions>, |
148 | | -) -> napi::Result<String> { |
149 | | - enum InputBytes { |
150 | | - File(Vec<u8>), |
151 | | - Buffer(Buffer), |
152 | | - } |
153 | | - |
| 186 | +) -> napi::Result<AsyncTask<FingerprintDiffTask>> { |
154 | 187 | 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()), |
166 | 190 | }; |
167 | 191 |
|
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 })) |
171 | 193 | } |
172 | 194 |
|
173 | 195 | /* -------------------------------- PNG decode -------------------------------- */ |
|
0 commit comments