Mercurial > touhou
changeset 781:5b43c42fa680
Stop exposing PBG3 to Python
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Sun, 09 Nov 2025 19:50:35 +0100 |
| parents | 1ada4036ab88 |
| children | a30ce01b9154 |
| files | python/src/lib.rs |
| diffstat | 1 files changed, 28 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -7,6 +7,7 @@ use std::fs::File; use std::io::BufReader; use std::path::PathBuf; +use std::sync::{Arc, Mutex}; #[cfg(feature = "glide")] mod glide; @@ -74,60 +75,20 @@ } } -#[pyclass(module = "libtouhou")] -struct PBG3 { - filename: PathBuf, - inner: pbg3::PBG3<BufReader<File>>, -} - -impl PBG3 { - fn get_file_internal(&mut self, name: &str) -> Vec<u8> { - self.inner.get_file(name, true).unwrap() - } -} - -#[pymethods] -impl PBG3 { - #[staticmethod] - fn from_filename(filename: PathBuf) -> PyResult<PBG3> { - let inner = pbg3::from_path_buffered(&filename)?; - Ok(PBG3 { - filename, - inner - }) - } - - fn __repr__(&self) -> String { - format!("PBG3({})", self.filename.to_str().unwrap()) - } - - #[getter] - fn file_list(&self) -> Vec<String> { - self.inner.list_files().cloned().collect() - } - - fn list_files(&self) -> Vec<String> { - self.inner.list_files().cloned().collect() - } - - fn get_file(&mut self, py: Python, name: &str) -> Py<PyBytes> { - let data = self.get_file_internal(name); - PyBytes::new(py, &data).into() - } -} - /// A loader for Touhou files. -#[pyclass(module = "libtouhou", get_all, subclass)] +#[pyclass(module = "libtouhou", subclass)] #[derive(Default)] struct Loader { /// The file names to the possible executable. + #[pyo3(get)] exe_files: Vec<PathBuf>, /// The path to the game directory. + #[pyo3(get)] game_dir: Option<PathBuf>, /// A map from inner filenames to the archive containing them. - known_files: HashMap<String, Py<PBG3>>, + known_files: HashMap<String, Arc<Mutex<pbg3::PBG3<BufReader<File>>>>>, } #[pymethods] @@ -146,7 +107,7 @@ /// /// paths_lists is a list of ':'-separated glob patterns, the first matching file will be used /// and the other ones ignored. - fn scan_archives(&mut self, py: Python, paths_lists: Vec<String>) -> PyResult<()> { + fn scan_archives(&mut self, paths_lists: Vec<String>) -> PyResult<()> { for paths in paths_lists.iter() { let found_paths: Vec<_> = paths.split(':').map(|path| { glob::glob(if let Some(game_dir) = self.game_dir.as_ref() { @@ -162,36 +123,41 @@ if let Some(extension) = path.extension() && extension == "exe" { self.exe_files.extend(found_paths); } else { - let pbg3 = PBG3::from_filename(path.to_owned())?; - let filenames = pbg3.list_files(); - let pbg3 = Py::new(py, pbg3)?; + let pbg3 = pbg3::from_path_buffered(path)?; + let filenames: Vec<_> = pbg3.list_files().cloned().collect(); + let pbg3 = Arc::new(Mutex::new(pbg3)); for name in filenames { - self.known_files.insert(name.clone(), Py::clone_ref(&pbg3, py)); + self.known_files.insert(name.clone(), Arc::clone(&pbg3)); } } } Ok(()) } - /// Return the given file as an io.BytesIO object. - fn get_file(&self, py: Python, name: String) -> PyResult<Py<PyAny>> { - if let Some(archive) = self.known_files.get(&name) { - let mut archive = archive.borrow_mut(py); - let bytes = archive.get_file(py, &name); - let io = py.import("io")?; - let bytesio_class = io.dict().get_item("BytesIO")?.unwrap(); - let file = bytesio_class.call1((bytes,))?; - Ok(file.unbind()) + /// Return the given file as a Vec<u8>. + fn get_file_internal(&self, name: &str) -> PyResult<Vec<u8>> { + if let Some(archive) = self.known_files.get(name) { + let mut archive = archive.lock().unwrap(); + let bytes = archive.get_file(name, true)?; + Ok(bytes) } else { Err(PyKeyError::new_err(format!("Unknown file {name:?}"))) } } + /// Return the given file as an io.BytesIO object. + fn get_file(&self, py: Python, name: String) -> PyResult<Py<PyAny>> { + let vec = self.get_file_internal(&name)?; + let bytes = PyBytes::new(py, &vec); + let io = py.import("io")?; + let bytesio_class = io.dict().get_item("BytesIO")?.unwrap(); + let file = bytesio_class.call1((bytes,))?; + Ok(file.unbind()) + } + fn get_stage(&self, py: Python, name: String) -> PyResult<Py<PyStage>> { - let archive = self.known_files.get(&name).unwrap(); - let mut archive = archive.borrow_mut(py); - let bytes = archive.get_file_internal(&name); - let (_, inner) = stage::Stage::from_slice(&bytes).unwrap(); + let vec = self.get_file_internal(&name)?; + let (_, inner) = stage::Stage::from_slice(&vec).unwrap(); Ok(Py::new(py, PyStage { inner })?) } }
