pub use scale_info::MetaType;
use scale_info::{
scale::{Encode, Output},
PortableRegistry, Registry,
};
use crate::prelude::{
mem::{transmute, MaybeUninit},
Box, String, Vec,
};
pub(crate) fn with_optimized_encode<T, E: Encode>(payload: E, f: impl FnOnce(&[u8]) -> T) -> T {
struct ExternalBufferOutput<'a> {
buffer: &'a mut [MaybeUninit<u8>],
offset: usize,
}
impl Output for ExternalBufferOutput<'_> {
fn write(&mut self, bytes: &[u8]) {
let end_offset = self.offset + bytes.len();
let this = unsafe { self.buffer.get_unchecked_mut(self.offset..end_offset) };
this.copy_from_slice(unsafe {
transmute::<&[u8], &[core::mem::MaybeUninit<u8>]>(bytes)
});
self.offset = end_offset;
}
}
gcore::stack_buffer::with_byte_buffer(payload.encoded_size(), |buffer| {
let mut output = ExternalBufferOutput { buffer, offset: 0 };
payload.encode_to(&mut output);
let ExternalBufferOutput { buffer, offset } = output;
let payload = unsafe { &*(&buffer[..offset] as *const _ as *const [u8]) };
f(payload)
})
}
pub fn to_hex_registry(meta_types: Vec<MetaType>) -> String {
let mut registry = Registry::new();
registry.register_types(meta_types);
let registry: PortableRegistry = registry.into();
hex::encode(registry.encode())
}
pub fn to_wasm_ptr<T: AsRef<[u8]>>(bytes: T) -> *mut [i32; 2] {
Box::into_raw(Box::new([
bytes.as_ref().as_ptr() as _,
bytes.as_ref().len() as _,
]))
}
pub fn to_leak_ptr(bytes: impl Into<Vec<u8>>) -> *mut [i32; 2] {
let bytes = bytes.into();
let ptr = Box::into_raw(Box::new([bytes.as_ptr() as _, bytes.len() as _]));
core::mem::forget(bytes);
ptr
}