use std::fmt::Debug;
use std::mem;
use std::ptr::{copy_nonoverlapping, null, null_mut};
use crate::lol::wad::entry::EntryLoc;
use crate::lol::wad::toc_type::{Entry, EntryEx, EntryV1, EntryV3_4, Header, HeaderV1, Toc, Version};
use crate::lol::io;
impl Toc<'_>{
fn read_raw<T, B>(&mut self, src: &mut io::bytes::Bytes, header_raw: &mut T, entry_raw: &mut B) -> *const u8
where T: Default + Header,
B:Default + EntryEx +Debug,
{
if src.0.size()< size_of_val(header_raw) {
return "Not enough data for Header".as_ptr() as _;
}
unsafe { std::ptr::copy_nonoverlapping(src.0.data(),
header_raw as *mut _ as *mut u8,
size_of_val(header_raw) ) };
if header_raw.get_desc_size() as usize != (size_of_val(entry_raw)) {
return "Bad Header::desc_size.".as_ptr() as _;
}
if src.0.size() < header_raw.get_desc_offset() as usize {
return "Bad Header::desc_offset.".as_ptr() as _;
}
if (src.0.size() - header_raw.get_desc_offset() as usize) < (size_of_val(entry_raw) * header_raw.get_desc_count() as usize) {
return "Not enough data for TOC.".as_ptr() as _;
}
self.entries.clear();
self.entries.reserve(header_raw.get_desc_count() as usize);
for i in 0..header_raw.get_desc_count() as usize{
unsafe { std::ptr::copy_nonoverlapping(
src.0.data().add(header_raw.get_desc_offset() as usize).add(size_of_val(entry_raw) *i ),
entry_raw as *mut _ as *mut u8,
size_of_val(entry_raw) ) };
self.entries.push(
Entry {
name: entry_raw.get_name(),
loc: EntryLoc {
r#type: entry_raw.get_type(),
subchunk_count: entry_raw.get_subchunk_count(),
subchunk_index: if entry_raw.get_subchunk_index() ==0 {entry_raw.get_subchunk_index_for_4().to_u32()} else {entry_raw.get_subchunk_index() as u32},
offset: entry_raw.get_offset() as _,
size: entry_raw.get_size() as _,
size_decompressed: entry_raw.get_size_decompressed() as _,
checksum: entry_raw.get_checksum(),
}
}
);
}
self.signature = header_raw.get_signature().clone();
null_mut()
}
pub fn read(&mut self, src: &mut io::bytes::Bytes) -> *const u8 {
if src.0.size() < size_of::<Version>(){
return null();
}
unsafe { copy_nonoverlapping(src.0.data(), &mut self.version as *mut _ as *mut u8, size_of::<Version>()) };
if self.version.magic.cmp(&[0u8;2]) == std::cmp::Ordering::Equal
&& self.version.major.cmp(&0) == std::cmp::Ordering::Equal
&& self.version.minor.cmp(&0) == std::cmp::Ordering::Equal
{
return null();
}
if !self.version.is_wad(){
return "Bad Version::magic.".as_ptr();
}
match self.version.major {
0 => {
},
1 => {
let mut header_raw = HeaderV1::default();
let mut entry_raw = EntryV1::default();
self.read_raw(src, &mut header_raw, &mut entry_raw);
self.latest_entry_t = Box::new(entry_raw);
self.latest_header_t= Box::new(header_raw);
},
2 => {
let mut header_raw = super::toc_type::HeaderV2::default();
let mut entry_raw = super::toc_type::EntryV2::default();
self.read_raw(src, &mut header_raw, &mut entry_raw);
self.latest_entry_t = Box::new(entry_raw);
self.latest_header_t= Box::new(header_raw);
},
3 => {
match self.version.minor {
0 =>{
let mut header_raw = super::toc_type::HeaderV3::default();
let mut entry_raw = super::toc_type::EntryV3::default();
self.read_raw(src, &mut header_raw, &mut entry_raw);
self.latest_entry_t = Box::new(entry_raw);
self.latest_header_t= Box::new(header_raw);
},
1=>{
},
2=>{
},
3=> {
let mut header_raw = super::toc_type::HeaderV3::default();
let mut entry_raw = super::toc_type::EntryV3_1::default();
self.read_raw(src, &mut header_raw, &mut entry_raw);
},
4=>{
let mut header_raw = super::toc_type::HeaderV3::default();
let mut entry_raw = super::toc_type::EntryV3_4::default();
self.read_raw(src, &mut header_raw, &mut entry_raw);
self.latest_entry_t = Box::new(entry_raw);
self.latest_header_t= Box::new(header_raw);
}
_ =>{
let mut header_raw = super::toc_type::HeaderV3::default();
let mut entry_raw: EntryV3_4 = unsafe { mem::zeroed() };
self.read_raw(src, &mut header_raw, &mut entry_raw);
self.latest_entry_t = Box::new(entry_raw);
self.latest_header_t= Box::new(header_raw);
},
}
},
_ =>{
return "Bad Wad::Version::major.".as_ptr();
}
}
null()
}
}