#[cfg(feature = "wasm")]
use crate::generate::core::PlatformCallbacks;
#[cfg(feature = "wasm")]
use crate::generate_error::{ProofModeError, Result};
#[cfg(feature = "wasm")]
use crate::generate_types::*;
#[cfg(feature = "wasm")]
use std::collections::HashMap;
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "wasm")]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
type ProofCallbacks;
#[wasm_bindgen(method, js_name = getDeviceInfo)]
fn get_device_info(this: &ProofCallbacks) -> JsValue;
#[wasm_bindgen(method, js_name = getLocationInfo)]
fn get_location_info(this: &ProofCallbacks) -> JsValue;
#[wasm_bindgen(method, js_name = getNetworkInfo)]
fn get_network_info(this: &ProofCallbacks) -> JsValue;
#[wasm_bindgen(method, js_name = saveData)]
fn save_data(this: &ProofCallbacks, hash: &str, filename: &str, data: &[u8]) -> bool;
#[wasm_bindgen(method, js_name = saveText)]
fn save_text(this: &ProofCallbacks, hash: &str, filename: &str, text: &str) -> bool;
#[wasm_bindgen(method, js_name = signData)]
fn sign_data(this: &ProofCallbacks, data: &[u8]) -> JsValue;
#[wasm_bindgen(method, js_name = notarizeHash)]
fn notarize_hash(this: &ProofCallbacks, hash: &str) -> JsValue;
}
#[cfg(feature = "wasm")]
pub struct WasmCallbacks {
js_callbacks: ProofCallbacks,
}
#[cfg(feature = "wasm")]
impl WasmCallbacks {
pub fn new(js_callbacks: ProofCallbacks) -> Self {
Self { js_callbacks }
}
}
#[cfg(feature = "wasm")]
impl PlatformCallbacks for WasmCallbacks {
fn get_device_info(&self) -> Option<DeviceData> {
let js_value = self.js_callbacks.get_device_info();
if js_value.is_null() || js_value.is_undefined() {
None
} else {
serde_wasm_bindgen::from_value(js_value).ok()
}
}
fn get_location_info(&self) -> Option<LocationData> {
let js_value = self.js_callbacks.get_location_info();
if js_value.is_null() || js_value.is_undefined() {
None
} else {
serde_wasm_bindgen::from_value(js_value).ok()
}
}
fn get_network_info(&self) -> Option<NetworkData> {
let js_value = self.js_callbacks.get_network_info();
if js_value.is_null() || js_value.is_undefined() {
None
} else {
serde_wasm_bindgen::from_value(js_value).ok()
}
}
fn save_data(&self, hash: &str, filename: &str, data: &[u8]) -> Result<()> {
if self.js_callbacks.save_data(hash, filename, data) {
Ok(())
} else {
Err(ProofModeError::Storage(
"Failed to save data via JS callback".to_string(),
))
}
}
fn save_text(&self, hash: &str, filename: &str, text: &str) -> Result<()> {
if self.js_callbacks.save_text(hash, filename, text) {
Ok(())
} else {
Err(ProofModeError::Storage(
"Failed to save text via JS callback".to_string(),
))
}
}
fn sign_data(&self, data: &[u8]) -> Result<Option<Vec<u8>>> {
let js_value = self.js_callbacks.sign_data(data);
if js_value.is_null() || js_value.is_undefined() {
Ok(None)
} else {
match serde_wasm_bindgen::from_value::<Vec<u8>>(js_value) {
Ok(data) => Ok(Some(data)),
Err(_) => Ok(None),
}
}
}
fn notarize_hash(&self, hash: &str) -> Result<Option<NotarizationData>> {
let js_value = self.js_callbacks.notarize_hash(hash);
if js_value.is_null() || js_value.is_undefined() {
Ok(None)
} else {
match serde_wasm_bindgen::from_value(js_value) {
Ok(data) => Ok(Some(data)),
Err(_) => Ok(None),
}
}
}
fn report_progress(&self, _message: &str) {
}
}
#[cfg(feature = "wasm")]
#[wasm_bindgen]
pub fn generate_proof_wasm(
media_data: &[u8],
metadata_json: &str,
js_callbacks: ProofCallbacks,
) -> std::result::Result<String, JsValue> {
let metadata: HashMap<String, String> = serde_json::from_str(metadata_json)
.map_err(|e| JsValue::from_str(&format!("Invalid metadata JSON: {}", e)))?;
let has_location = metadata.contains_key("latitude") && metadata.contains_key("longitude");
let config = ProofModeConfig {
auto_notarize: false,
track_location: has_location,
track_device_id: true,
track_network: true,
add_credentials: false,
embed_c2pa: false,
};
let callbacks = WasmCallbacks::new(js_callbacks);
let generator = crate::generate::core::ProofGenerator::new(config);
match generator.generate_proof(media_data, metadata, &callbacks) {
Ok(hash) => Ok(hash),
Err(e) => Err(JsValue::from_str(&format!(
"Proof generation failed: {}",
e
))),
}
}
#[cfg(feature = "wasm")]
#[wasm_bindgen]
pub fn get_file_hash(media_data: &[u8]) -> String {
crate::crypto::hash::calculate_hash(media_data)
}