use std::{fs::File, sync::{atomic::{AtomicPtr, AtomicUsize, Ordering}, Arc, Mutex, OnceLock}};
use crate::lol::io::sys_type::Error;
use memmap2::Mmap;
use super::sys_type::{Result, Lolfileresult};
type Handle = Arc<Mutex<Option<Vec<Mmap>>>>;
static HANDLE: OnceLock<Handle> = OnceLock::new();
static PTR: AtomicPtr<u8> = AtomicPtr::new(std::ptr::null_mut());
static LEN: AtomicUsize = AtomicUsize::new(0);
fn get_handle() -> &'static Handle {
HANDLE.get_or_init(|| {
Arc::new(Mutex::new(Some(Vec::<Mmap>::new())))
})
}
fn push_mmap(mmap: Mmap) -> std::io::Result<()> {
let handle = get_handle();
let mut map = handle.lock().unwrap();
map.as_mut().unwrap().push(mmap);
Ok(())
}
pub struct LOLfile<T>(pub T);
impl Lolfileresult<LOLfile<Handle>, Error> for LOLfile<Handle> {
type Output = Result<LOLfile<Handle>, Error>;
fn file_open(path: &std::path::Path, write: bool) -> Result<LOLfile<Handle>, Error> {
if write {
if path.extension().and_then(|s| s.to_str()) == Some("client") {
let newpath = path.with_extension("");
if newpath .is_dir() {
let _= path.to_path_buf();
} else {
std::fs::create_dir(newpath).unwrap();
}
} else {
let _ = path.to_path_buf();
}
}
let fileopne = File::open(path).unwrap();
let mmap = unsafe { Mmap::map(&fileopne) }.unwrap();
let ptr = mmap.as_ptr() as *mut u8;
let len = mmap.len();
push_mmap(mmap).unwrap(); PTR.store(ptr as *mut u8, Ordering::Release);
LEN.store(len, Ordering::Release);
if HANDLE.get().is_none() {
return Result::Err(Error::OpenError);
}
Self::Output::Ok(LOLfile(HANDLE.get().unwrap().clone()))
}
fn file_size(&self) -> Result<usize, Error> {
let len = LEN.load(Ordering::Acquire);
Result::Ok(len)
}
fn file_resize(&mut self, count: usize) -> Result<usize, Error> {
LEN.store(count, Ordering::Release);
Result::Ok(count)
}
fn file_mmap(&mut self, count: usize, _write: bool) -> Result<*mut u8, Error> {
if count == 0 {
return Result::Err(Error::MmapError);
}
let data = PTR.load(Ordering::Acquire);
Result::Ok(data as _)
}
fn file_munmap( _count: usize) -> Result<(), Error> {
PTR.store(std::ptr::null_mut(), Ordering::Release);
LEN.store(0, Ordering::Release);
let handle = get_handle();
let mut map =handle.lock().unwrap();
let maps = map.as_mut().unwrap();
for map in maps {
drop(map.to_owned());
}
Result::Ok(())
}
}