1#[cfg(feature = "wasm")]
8use wasm_bindgen::prelude::*;
9
10use crate::error::Error;
11
12#[cfg(feature = "wasm")]
19pub fn error_to_js_value(error: Error) -> JsValue {
20 let message = match error {
22 Error::InvalidAlgorithm { .. } => "Invalid algorithm specified",
23 Error::InvalidKeySize { .. } => "Invalid key size",
24 Error::InvalidMessageSize { .. } => "Invalid message size",
25 Error::InvalidNonceSize { .. } => "Invalid nonce size",
26 Error::InvalidSignatureSize { .. } => "Invalid signature",
27 Error::InvalidCiphertextSize { .. } => "Invalid ciphertext",
28 Error::InvalidPlaintextSize { .. } => "Invalid plaintext",
29 Error::InvalidKeyFormat => "Invalid key material",
30 Error::InvalidSecurityLevel { .. } => "Invalid security level",
31 Error::NotImplemented { .. } => "Feature not implemented",
32 Error::ProviderNotConfigured { .. } => "Provider not configured",
33 Error::VerificationFailed { .. } => "Verification failed",
34 Error::EncryptionFailed { .. } => "Encryption failed",
35 Error::DecryptionFailed { .. } => "Decryption failed",
36 Error::KeyGenerationFailed { .. } => "Key generation failed",
37 Error::RandomGenerationFailed { .. } => "Random generation failed",
38 Error::SigningFailed { .. } => "Signing failed",
39 Error::MemoryAllocationFailed { .. } => "Memory allocation failed",
40 Error::InternalError { .. } => "Internal error",
41 Error::UnsupportedOperation { .. } => "Unsupported operation",
42 Error::InvalidState { .. } => "Invalid context state",
43 Error::PluginDependencyError { .. } => "Plugin dependency error",
44 Error::PluginVersionIncompatible { .. } => "Plugin version incompatible",
45 Error::InvalidKey { .. } => "Invalid key",
46 Error::UnsupportedAlgorithm { .. } => "Unsupported algorithm",
47 Error::AuthenticationFailed { .. } => "Authentication failed",
48 Error::InvalidAssociatedDataSize { .. } => "Invalid associated data size",
49 Error::InvalidTagSize { .. } => "Invalid tag size",
50 Error::InvalidHashSize { .. } => "Invalid hash size",
51 Error::InvalidRandomnessSize { .. } => "Invalid randomness size",
52 Error::RandomBytesLengthInvalid { .. } => "Invalid random length",
53 Error::HexDecode(..) => "Invalid hex encoding",
54 Error::BufferTooSmall { .. } => "Insufficient buffer capacity",
55 };
56
57 JsValue::from_str(message)
58}
59
60#[cfg(feature = "wasm")]
67pub fn convert_result<T>(result: Result<T, Error>) -> Result<T, JsValue> {
68 result.map_err(error_to_js_value)
69}
70
71#[cfg(feature = "wasm")]
78pub fn parse_algorithm_wasm(algorithm: &str) -> Result<crate::api::Algorithm, JsValue> {
79 if algorithm.len() > 64 {
81 return Err(JsValue::from_str("Algorithm name too long"));
82 }
83
84 if algorithm.chars().any(|c| c.is_control()) {
87 return Err(JsValue::from_str("Invalid algorithm name format"));
88 }
89
90 match crate::wasm::conversions::WasmConversions::string_to_algorithm(algorithm) {
91 Ok(a) => Ok(a),
92 Err(Error::UnsupportedAlgorithm { .. }) => Err(JsValue::from_str("Unsupported algorithm")),
93 Err(_) => Err(JsValue::from_str("Invalid algorithm specified")),
94 }
95}
96
97#[cfg(feature = "wasm")]
104#[macro_export]
105macro_rules! wasm_result {
106 ($expr:expr) => {
107 match $expr {
108 Ok(value) => Ok(value),
109 Err(error) => Err($crate::wasm::error::error_to_js_value(error)),
110 }
111 };
112}
113
114#[cfg(feature = "wasm")]
121#[macro_export]
122macro_rules! wasm_validate {
123 ($condition:expr, $error_msg:expr) => {
124 if !$condition {
125 return Err(JsValue::from_str($error_msg));
126 }
127 };
128}
129
130#[cfg(feature = "wasm")]
137pub fn secure_serialize<T: serde::Serialize>(value: &T) -> Result<JsValue, JsValue> {
138 match serde_wasm_bindgen::to_value(value) {
139 Ok(js_value) => Ok(js_value),
140 Err(_) => Err(JsValue::from_str("Serialization error")),
141 }
142}
143
144#[cfg(feature = "wasm")]
151pub fn secure_deserialize<T: serde::de::DeserializeOwned>(value: &JsValue) -> Result<T, JsValue> {
152 match serde_wasm_bindgen::from_value(value.clone()) {
153 Ok(deserialized) => Ok(deserialized),
154 Err(_) => Err(JsValue::from_str("Deserialization error")),
155 }
156}
157
158#[cfg(test)]
159mod tests {
160
161 #[test]
162 #[cfg(target_arch = "wasm32")]
163 fn test_error_conversion() {
164 let error = Error::InvalidAlgorithm { algorithm: "test" };
165 let js_error = error_to_js_value(error);
166 assert!(js_error.is_string());
167 }
168
169 #[test]
170 #[cfg(target_arch = "wasm32")]
171 fn test_algorithm_parsing() {
172 assert!(parse_algorithm_wasm("sha3-256").is_ok());
173 assert_eq!(
174 parse_algorithm_wasm("mldsa65").unwrap(),
175 crate::api::Algorithm::MlDsa65
176 );
177 assert_eq!(
178 parse_algorithm_wasm("ML-DSA-65").unwrap(),
179 crate::api::Algorithm::MlDsa65
180 );
181 assert_eq!(
182 parse_algorithm_wasm("slh-dsa-shake256-128f-robust").unwrap(),
183 crate::api::Algorithm::SlhDsaShake256128fRobust
184 );
185 assert_eq!(
186 parse_algorithm_wasm("SlhDsaShake256128fRobust").unwrap(),
187 crate::api::Algorithm::SlhDsaShake256128fRobust
188 );
189 assert!(parse_algorithm_wasm("invalid").is_err());
190 assert!(parse_algorithm_wasm(&"a".repeat(100)).is_err());
191 }
192
193 #[test]
194 #[cfg(target_arch = "wasm32")]
195 fn test_secure_serialization() {
196 let value = serde_json::json!({"test": "value"});
197 let result = secure_serialize(&value);
198 assert!(result.is_ok());
199 }
200}