72 lines
2 KiB
Rust
72 lines
2 KiB
Rust
use std::fmt::{Display, Formatter};
|
|
use std::sync::OnceLock;
|
|
|
|
use widestring::{WideCStr, WideCString};
|
|
|
|
use crate::{Add, Container};
|
|
use crate::t_array::TArray;
|
|
|
|
type FStringPrintf = fn(handle: usize, fmt: *const u16);
|
|
static FSTRING_PRINTF: OnceLock<usize> = OnceLock::new();
|
|
|
|
pub trait Printf<T: ?Sized> {
|
|
/// Since rust does not support varargs in functions, it is recommended to call format!
|
|
fn printf<A: AsRef<T>>(handle: usize, fmt: A);
|
|
}
|
|
|
|
pub struct FString(pub(crate) TArray);
|
|
|
|
impl FString {
|
|
pub fn set_f_string_printf_ptr(f_string_printf: usize) {
|
|
FSTRING_PRINTF.set(f_string_printf).unwrap();
|
|
}
|
|
}
|
|
|
|
impl Printf<str> for FString {
|
|
#[inline(always)]
|
|
fn printf<A: AsRef<str>>(handle: usize, fmt: A) {
|
|
let tmp = WideCString::from_str(fmt).unwrap();
|
|
unsafe {
|
|
std::mem::transmute::<usize, FStringPrintf>(*fstring_printf())(
|
|
handle,
|
|
tmp.as_ucstr().as_ptr(),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Container<&'a WideCStr> for FString {
|
|
#[inline(always)]
|
|
fn read_container(&self) -> &'a WideCStr {
|
|
unsafe {
|
|
WideCStr::from_ptr(self.0.data_ptr as *const u16, self.0.len as usize - 1)
|
|
}.unwrap()
|
|
}
|
|
}
|
|
|
|
impl Add for FString {
|
|
fn add(&mut self, other: &mut Self) -> &mut Self {
|
|
let old_len = self.0.resize_grow(Some(other.0.len));
|
|
let src = unsafe {
|
|
std::slice::from_raw_parts_mut(other.0.data_ptr as *mut u16, other.0.len as usize)
|
|
};
|
|
let dst = unsafe {
|
|
std::slice::from_raw_parts_mut(self.0.data_ptr as *mut u16, self.0.len as usize)
|
|
};
|
|
dst[old_len as usize..other.0.len as usize].copy_from_slice(src);
|
|
// Clear the header of the original container
|
|
other.0.release_header_stack();
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Display for FString {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.read_container().to_string_lossy())
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn fstring_printf() -> &'static usize {
|
|
FSTRING_PRINTF.get().unwrap()
|
|
}
|