use crate::{ConversionError, ConversionOptions};
use serde::Serialize;
#[derive(Serialize)]
pub struct WasmErrorInfo {
pub error: String,
pub error_type: String,
pub details: String,
pub duc_data_length: usize,
pub conversion_context: Option<ConversionContext>,
}
#[derive(Serialize)]
pub struct ConversionContext {
pub has_offset: bool,
pub has_dimensions: bool,
pub has_zoom: bool,
pub has_scale: bool,
}
pub fn create_error_info(
error: &ConversionError,
duc_data_length: usize,
options: Option<&ConversionOptions>,
) -> WasmErrorInfo {
let error_type = std::any::type_name_of_val(error);
let details = match error {
ConversionError::InvalidDucData(msg) => {
format!("DUC parsing failed: {}", msg)
}
ConversionError::CoordinateOutOfBounds(x, y) => {
format!(
"Coordinate out of bounds: x={}, y={} (max allowed: ±{}). Note: This should be prevented by automatic scaling - the scaling logic may need investigation.",
x, y, crate::MAX_COORDINATE_MM
)
}
ConversionError::ScaleExceedsBounds(x, y, scale) => {
format!(
"Scale exceeds bounds: x={}, y={}, scale={} (max allowed: ±{}). This indicates the automatic scaling logic failed - investigate the scaling calculation.",
x, y, scale, crate::MAX_COORDINATE_MM
)
}
ConversionError::PrecisionTooHigh(precision) => {
format!("Precision too high: {} (min allowed: {})", precision, crate::MIN_PRECISION_MM)
}
ConversionError::PdfGenerationError(msg) => {
format!("PDF generation failed: {}", msg)
}
ConversionError::ResourceLoadError(msg) => {
format!("Resource loading failed: {}", msg)
}
};
let conversion_context = options.map(|opts| ConversionContext {
has_offset: match &opts.mode {
crate::ConversionMode::Crop { .. } => true,
crate::ConversionMode::Plot => false,
},
has_dimensions: match &opts.mode {
crate::ConversionMode::Crop { width, height, .. } => width.is_some() && height.is_some(),
crate::ConversionMode::Plot => false,
},
has_zoom: false, has_scale: opts.scale.is_some(),
});
WasmErrorInfo {
error: error.to_string(),
error_type: error_type.to_string(),
details,
duc_data_length,
conversion_context,
}
}
pub fn log_error_details(error: &ConversionError, duc_data_length: usize, context: &str) {
println!("=== DUC to PDF Conversion Error ===");
println!("Context: {}", context);
println!("Error type: {:?}", std::any::type_name_of_val(error));
println!("Error details: {}", error);
println!("DUC data length: {} bytes", duc_data_length);
match error {
ConversionError::InvalidDucData(msg) => {
println!("DUC parsing failed: {}", msg);
println!("Possible causes: corrupted DUC data, incomplete file transfer, or incompatible DUC version");
}
ConversionError::CoordinateOutOfBounds(x, y) => {
println!("Coordinate out of bounds: x={}, y={} (max allowed: ±{})", x, y, crate::MAX_COORDINATE_MM);
println!("⚠️ This should be prevented by automatic scaling! Investigate the scaling logic in:");
println!(" - calculate_required_scale() function");
println!(" - validate_all_coordinates_with_scale() function");
println!(" - DucDataScaler scaling application");
}
ConversionError::ScaleExceedsBounds(x, y, scale) => {
println!("Scale exceeds bounds: x={}, y={}, scale={} (max allowed: ±{})", x, y, scale, crate::MAX_COORDINATE_MM);
println!("⚠️ User-provided scale still exceeds bounds! The scaling validation may need improvement.");
}
ConversionError::PrecisionTooHigh(precision) => {
println!("Precision too high: {} (min allowed: {})", precision, crate::MIN_PRECISION_MM);
}
ConversionError::PdfGenerationError(msg) => {
println!("PDF generation failed: {}", msg);
println!("Possible causes: memory issues, PDF content problems, or resource loading failures");
}
ConversionError::ResourceLoadError(msg) => {
println!("Resource loading failed: {}", msg);
println!("Possible causes: missing embedded resources, font loading issues, or image processing failures");
}
}
}
pub fn log_crop_details(offset_x: f64, offset_y: f64, width: Option<f64>, height: Option<f64>) {
println!("Crop operation details:");
println!(" Offset: x={}, y={}", offset_x, offset_y);
if let Some(w) = width {
println!(" Width: {}", w);
}
if let Some(h) = height {
println!(" Height: {}", h);
}
}
pub fn validate_basic_inputs(duc_data: &[u8], offset_x: Option<f64>, offset_y: Option<f64>, width: Option<f64>, height: Option<f64>) -> Result<(), String> {
if duc_data.is_empty() {
return Err("DUC data is empty".to_string());
}
if let Some(x) = offset_x {
if !x.is_finite() {
return Err(format!("Invalid offset_x: {} (must be finite)", x));
}
}
if let Some(y) = offset_y {
if !y.is_finite() {
return Err(format!("Invalid offset_y: {} (must be finite)", y));
}
}
if let Some(w) = width {
if !w.is_finite() || w <= 0.0 {
return Err(format!("Invalid width: {} (must be positive finite)", w));
}
}
if let Some(h) = height {
if !h.is_finite() || h <= 0.0 {
return Err(format!("Invalid height: {} (must be positive finite)", h));
}
}
Ok(())
}
pub fn error_to_wasm_bytes(error_info: &WasmErrorInfo) -> Vec<u8> {
let error_json = serde_json::to_string(error_info).unwrap_or_else(|e| {
format!(r#"{{"error":"Failed to serialize error","details":"{}"}}"#, e)
});
let mut result = b"ERROR:".to_vec();
result.extend_from_slice(error_json.as_bytes());
result
}