#![allow(clippy::needless_pass_by_value)]
use boa_engine::realm::Realm;
use boa_engine::{Context, JsResult, boa_module};
#[cfg(test)]
mod tests;
const FORGIVING: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new(
&base64::alphabet::STANDARD,
base64::engine::general_purpose::GeneralPurposeConfig::new()
.with_decode_padding_mode(base64::engine::DecodePaddingMode::Indifferent),
);
#[boa_module]
pub mod js_module {
use super::FORGIVING;
use base64::Engine as _;
use boa_engine::{JsResult, js_error};
#[allow(clippy::cast_possible_truncation)]
pub fn btoa(data: String) -> JsResult<String> {
let bytes: Vec<u8> = data
.chars()
.map(|c| {
let cp = c as u32;
if cp > 0xFF {
Err(js_error!("InvalidCharacterError: The string to be encoded contains characters outside of the Latin1 range."))
} else {
Ok(cp as u8)
}
})
.collect::<JsResult<Vec<u8>>>()?;
Ok(base64::engine::general_purpose::STANDARD.encode(&bytes))
}
pub fn atob(data: String) -> JsResult<String> {
let cleaned: String = data
.chars()
.filter(|c| !matches!(c, ' ' | '\t' | '\n' | '\x0C' | '\r'))
.collect();
let bytes = FORGIVING.decode(cleaned.as_bytes()).map_err(|_| {
js_error!("InvalidCharacterError: The string to be decoded is not correctly encoded.")
})?;
Ok(bytes.into_iter().map(char::from).collect())
}
}
pub fn register(realm: Option<Realm>, context: &mut Context) -> JsResult<()> {
js_module::boa_register(realm, context)
}