mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-26 21:57:08 +08:00
ADD BSE support for v1
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
use super::bse::*;
|
||||||
use super::dsc::*;
|
use super::dsc::*;
|
||||||
use crate::ext::io::*;
|
use crate::ext::io::*;
|
||||||
use crate::scripts::base::*;
|
use crate::scripts::base::*;
|
||||||
@@ -6,7 +7,7 @@ use crate::utils::encoding::encode_string;
|
|||||||
use crate::utils::struct_pack::*;
|
use crate::utils::struct_pack::*;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use msg_tool_macro::*;
|
use msg_tool_macro::*;
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -130,7 +131,7 @@ impl<T: Read + Seek> Read for Entry<T> {
|
|||||||
format!("Failed to lock mutex: {}", e),
|
format!("Failed to lock mutex: {}", e),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
reader.seek(std::io::SeekFrom::Start(
|
reader.seek(SeekFrom::Start(
|
||||||
self.base_offset + self.header.offset as u64 + self.pos as u64,
|
self.base_offset + self.header.offset as u64 + self.pos as u64,
|
||||||
))?;
|
))?;
|
||||||
let bytes_read = buf.len().min(self.header.size as usize - self.pos);
|
let bytes_read = buf.len().min(self.header.size as usize - self.pos);
|
||||||
@@ -143,6 +144,46 @@ impl<T: Read + Seek> Read for Entry<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Read + Seek> Seek for Entry<T> {
|
||||||
|
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
|
||||||
|
let new_pos = match pos {
|
||||||
|
SeekFrom::Start(offset) => offset as usize,
|
||||||
|
SeekFrom::End(offset) => {
|
||||||
|
if offset < 0 {
|
||||||
|
if (-offset) as usize > self.header.size as usize {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidInput,
|
||||||
|
"Seek from end exceeds file length",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
self.header.size as usize - (-offset) as usize
|
||||||
|
} else {
|
||||||
|
self.header.size as usize + offset as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SeekFrom::Current(offset) => {
|
||||||
|
if offset < 0 {
|
||||||
|
if (-offset) as usize > self.pos {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidInput,
|
||||||
|
"Seek from current exceeds current position",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
self.pos.saturating_sub((-offset) as usize)
|
||||||
|
} else {
|
||||||
|
self.pos + offset as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.pos = new_pos;
|
||||||
|
Ok(self.pos as u64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stream_position(&mut self) -> std::io::Result<u64> {
|
||||||
|
Ok(self.pos as u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BgiArchive<T: Read + Seek + std::fmt::Debug> {
|
pub struct BgiArchive<T: Read + Seek + std::fmt::Debug> {
|
||||||
reader: Arc<Mutex<T>>,
|
reader: Arc<Mutex<T>>,
|
||||||
@@ -312,11 +353,41 @@ impl<'a, T: Iterator<Item = &'a BgiFileHeader>, R: Read + Seek + 'static> Iterat
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let reader = MemReader::new(decoded);
|
||||||
|
if reader.data.starts_with(b"BSE 1.") {
|
||||||
|
match BseReader::new(reader, detect_script_type, &entry.header.filename) {
|
||||||
|
Ok(bse_reader) => {
|
||||||
|
return Some(Ok(Box::new(bse_reader)));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Some(Err(anyhow::anyhow!(
|
||||||
|
"Failed to create BSE reader for '{}': {}",
|
||||||
|
entry.header.filename,
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
return Some(Ok(Box::new(MemEntry {
|
return Some(Ok(Box::new(MemEntry {
|
||||||
name: entry.header.filename.clone(),
|
name: entry.header.filename.clone(),
|
||||||
data: MemReader::new(decoded),
|
data: reader,
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
if buf.starts_with(b"BSE 1.") {
|
||||||
|
let filename = entry.header.filename.clone();
|
||||||
|
match BseReader::new(entry, detect_script_type, &filename) {
|
||||||
|
Ok(bse_reader) => {
|
||||||
|
return Some(Ok(Box::new(bse_reader)));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Some(Err(anyhow::anyhow!(
|
||||||
|
"Failed to create BSE reader for '{}': {}",
|
||||||
|
&filename,
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
entry.script_type = detect_script_type(&buf, buf.len(), &entry.header.filename).cloned();
|
entry.script_type = detect_script_type(&buf, buf.len(), &entry.header.filename).cloned();
|
||||||
Some(Ok(Box::new(entry)))
|
Some(Ok(Box::new(entry)))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user