use crate::check::utils::MessageType;
use crate::generate::core::PlatformCallbacks;
use crate::generate_error;
use crate::generate_types::*;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Debug, thiserror::Error, uniffi::Error)]
pub enum ProofModeError {
#[error("IO error: {message}")]
Io { message: String },
#[error("Generation error: {message}")]
Generation { message: String },
#[error("Check error: {message}")]
Check { message: String },
}
impl From<generate_error::ProofModeError> for ProofModeError {
fn from(err: generate_error::ProofModeError) -> Self {
ProofModeError::Generation {
message: err.to_string(),
}
}
}
#[uniffi::export(with_foreign)]
pub trait ProofModeCallbacks: Send + Sync {
fn get_location(&self) -> Option<LocationData>;
fn get_device_info(&self) -> Option<DeviceData>;
fn get_network_info(&self) -> Option<NetworkData>;
fn save_data(&self, hash: String, filename: String, data: Vec<u8>) -> bool;
fn save_text(&self, hash: String, filename: String, text: String) -> bool;
fn sign_data(&self, data: Vec<u8>) -> Option<Vec<u8>>;
fn report_progress(&self, message: String);
}
struct CallbacksAdapter {
inner: Arc<dyn ProofModeCallbacks>,
}
impl CallbacksAdapter {
fn new(callbacks: Arc<dyn ProofModeCallbacks>) -> Self {
Self { inner: callbacks }
}
}
impl PlatformCallbacks for CallbacksAdapter {
fn get_device_info(&self) -> Option<DeviceData> {
self.inner.get_device_info()
}
fn get_location_info(&self) -> Option<LocationData> {
self.inner.get_location()
}
fn get_network_info(&self) -> Option<NetworkData> {
self.inner.get_network_info()
}
fn save_data(&self, hash: &str, filename: &str, data: &[u8]) -> generate_error::Result<()> {
if self
.inner
.save_data(hash.to_string(), filename.to_string(), data.to_vec())
{
Ok(())
} else {
Err(generate_error::ProofModeError::Storage(
"Failed to save data via callback".to_string(),
))
}
}
fn save_text(&self, hash: &str, filename: &str, text: &str) -> generate_error::Result<()> {
if self
.inner
.save_text(hash.to_string(), filename.to_string(), text.to_string())
{
Ok(())
} else {
Err(generate_error::ProofModeError::Storage(
"Failed to save text via callback".to_string(),
))
}
}
fn sign_data(&self, data: &[u8]) -> generate_error::Result<Option<Vec<u8>>> {
Ok(self.inner.sign_data(data.to_vec()))
}
fn notarize_hash(&self, _hash: &str) -> generate_error::Result<Option<NotarizationData>> {
Ok(None)
}
fn report_progress(&self, message: &str) {
self.inner.report_progress(message.to_string());
}
}
#[uniffi::export]
pub fn generate_proof(
media_data: Vec<u8>,
metadata: HashMap<String, String>,
config: ProofModeConfig,
callbacks: Arc<dyn ProofModeCallbacks>,
) -> Result<String, ProofModeError> {
callbacks.report_progress("Starting proof generation...".to_string());
let adapter = CallbacksAdapter::new(Arc::clone(&callbacks));
let generator = crate::generate::core::ProofGenerator::new(config);
callbacks.report_progress("Generating proof...".to_string());
let hash = generator.generate_proof(&media_data, metadata, &adapter)?;
callbacks.report_progress(format!("Proof generation complete: {}", hash));
Ok(hash)
}
#[uniffi::export]
pub fn get_file_hash(media_data: Vec<u8>) -> String {
crate::crypto::hash::calculate_hash(&media_data)
}
#[uniffi::export]
pub fn get_version() -> String {
env!("CARGO_PKG_VERSION").to_string()
}
#[uniffi::export]
pub fn check_files(
file_paths: Vec<String>,
callbacks: Arc<dyn ProofModeCallbacks>,
) -> Result<String, ProofModeError> {
callbacks.report_progress("Starting file verification...".to_string());
let progress_cb = Arc::clone(&callbacks);
let reporter: crate::check::utils::ReporterCallback =
Arc::new(move |msg_type: MessageType, msg: String| {
let prefix = match msg_type {
MessageType::Status => "STATUS",
MessageType::Error => "ERROR",
MessageType::Complete => "COMPLETE",
};
progress_cb.report_progress(format!("{}: {}", prefix, msg));
});
let result =
crate::check::check_files(&file_paths, reporter).map_err(|e| ProofModeError::Check {
message: e.to_string(),
})?;
let json = serde_json::to_string(&result).map_err(|e| ProofModeError::Generation {
message: e.to_string(),
})?;
callbacks.report_progress("Verification complete!".to_string());
Ok(json)
}