pub(crate) fn get_external_references() -> Vec<v8::ExternalReference> {
vec![
v8::ExternalReference {
function: v8::MapFnTo::map_fn_to(atob),
},
v8::ExternalReference {
function: v8::MapFnTo::map_fn_to(btoa),
},
]
}
pub(crate) fn register_bindings(scope: &mut v8::PinScope, bindings: v8::Local<v8::Object>) {
let name = v8::String::new(scope, "atob").unwrap();
let value = v8::Function::new(scope, atob).unwrap();
bindings.set(scope, name.into(), value.into());
let name = v8::String::new(scope, "btoa").unwrap();
let value = v8::Function::new(scope, btoa).unwrap();
bindings.set(scope, name.into(), value.into());
}
#[inline]
fn atob(scope: &mut v8::PinScope, args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue) {
if !crate::error::check_arg_count(scope, &args, 1, "atob") {
return;
}
let input = args.get(0);
if input.is_null_or_undefined() {
crate::error::throw_type_error(scope, "Failed to convert argument to string");
return;
}
let input_str = {
v8::tc_scope!(let tc, scope);
input.to_string(tc)
};
let input_str = match input_str {
Some(s) => s,
None => {
crate::error::throw_type_error(scope, "Failed to convert argument to string");
return;
}
};
let str_len = input_str.length();
if str_len == 0 {
let result = v8::String::new(scope, "").unwrap();
rv.set(result.into());
return;
}
let mut input_bytes = vec![0u8; str_len];
input_str.write_one_byte_v2(scope, 0, &mut input_bytes, v8::WriteFlags::empty());
input_bytes.retain(|&b| !b.is_ascii_whitespace());
if !input_bytes.len().is_multiple_of(4) {
crate::error::throw_error(scope, "Invalid base64 string length");
return;
}
let decoded = match base64_simd::forgiving_decode_inplace(&mut input_bytes) {
Ok(decoded_slice) => decoded_slice,
Err(_) => {
crate::error::throw_error(scope, "Invalid base64 string");
return;
}
};
let result = v8::String::new_from_one_byte(scope, decoded, v8::NewStringType::Normal).unwrap();
rv.set(result.into());
}
#[inline]
fn btoa(scope: &mut v8::PinScope, args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue) {
if !crate::error::check_arg_count(scope, &args, 1, "btoa") {
return;
}
let input = args.get(0);
if input.is_null_or_undefined() {
crate::error::throw_type_error(scope, "Failed to convert argument to string");
return;
}
let input_str = {
v8::tc_scope!(let tc, scope);
input.to_string(tc)
};
let input_str = match input_str {
Some(s) => s,
None => {
crate::error::throw_type_error(scope, "Failed to convert argument to string");
return;
}
};
let v8_str_len = input_str.length();
if input_str.contains_only_onebyte() {
let mut bytes = vec![0u8; v8_str_len];
input_str.write_one_byte_v2(scope, 0, &mut bytes, v8::WriteFlags::empty());
let encoded = base64_simd::STANDARD.encode_to_string(&bytes);
let result = v8::String::new(scope, &encoded).unwrap();
rv.set(result.into());
} else {
let input_str_rust = input_str.to_rust_string_lossy(scope);
let mut bytes = Vec::with_capacity(v8_str_len);
for ch in input_str_rust.chars() {
if ch as u32 > 0xFF {
crate::error::throw_error(
scope,
"The string to be encoded contains characters outside of the Latin1 range.",
);
return;
}
bytes.push(ch as u8);
}
let encoded = base64_simd::STANDARD.encode_to_string(&bytes);
let result = v8::String::new(scope, &encoded).unwrap();
rv.set(result.into());
}
}