From 06482e2218edc975c1b4bca5b94cdbc2b9a698a0 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Sun, 18 Jan 2026 22:46:09 +0800 Subject: [PATCH] feat: finish sonnet expose interface --- BallanceTasSonnet/src/lib.rs | 415 ++++++++++++++++++++++- BallanceTasSonnet/src/tasfile.rs | 7 - BallanceTasSonnet/src/wrapped/tasfile.rs | 16 +- 3 files changed, 416 insertions(+), 22 deletions(-) delete mode 100644 BallanceTasSonnet/src/tasfile.rs diff --git a/BallanceTasSonnet/src/lib.rs b/BallanceTasSonnet/src/lib.rs index 4f7d2fd..3432a2a 100644 --- a/BallanceTasSonnet/src/lib.rs +++ b/BallanceTasSonnet/src/lib.rs @@ -4,11 +4,416 @@ pub(crate) mod wrapped; #[pymodule] mod tasfile { - use pyo3::prelude::*; + use pyo3::{exceptions::PyRuntimeError, prelude::*}; + use crate::wrapped::tasfile::{ + Error as RsTasError, TasFile as RsTasFile, TasFrame as RsTasFrame, TasKey as RsTasKey + }; - /// Formats the sum of two numbers as string. - #[pyfunction] - fn sum_as_string(a: usize, b: usize) -> PyResult { - Ok((a + b).to_string()) + impl From for PyErr { + fn from(error: RsTasError) -> Self { + PyRuntimeError::new_err(error.to_string()) + } } + + #[pyclass(eq, eq_int)] + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + enum TasKey { + #[pyo3(name = "KEY_UP")] + KeyUp, + #[pyo3(name = "KEY_DOWN")] + KeyDown, + #[pyo3(name = "KEY_LEFT")] + KeyLeft, + #[pyo3(name = "KEY_RIGHT")] + KeyRight, + #[pyo3(name = "KEY_SHIFT")] + KeyShift, + #[pyo3(name = "KEY_SPACE")] + KeySpace, + #[pyo3(name = "KEY_Q")] + KeyQ, + #[pyo3(name = "KEY_ESC")] + KeyEsc, + #[pyo3(name = "KEY_ENTER")] + KeyEnter, + } + + impl From for RsTasKey { + fn from(key: TasKey) -> RsTasKey { + match key { + TasKey::KeyUp => RsTasKey::KeyUp, + TasKey::KeyDown => RsTasKey::KeyDown, + TasKey::KeyLeft => RsTasKey::KeyLeft, + TasKey::KeyRight => RsTasKey::KeyRight, + TasKey::KeyShift => RsTasKey::KeyShift, + TasKey::KeySpace => RsTasKey::KeySpace, + TasKey::KeyQ => RsTasKey::KeyQ, + TasKey::KeyEsc => RsTasKey::KeyEsc, + TasKey::KeyEnter => RsTasKey::KeyEnter, + } + } + } + + // #[pyclass] + // #[derive(Clone)] + // pub struct PyTasFrame { + // inner: TasFrame, + // } + + // // Constructor for PyTasFrame + // impl PyTasFrame { + // fn new_from_inner(inner: TasFrame) -> Self { + // PyTasFrame { inner } + // } + // } + + // #[pymethods] + // impl PyTasFrame { + // #[new] + // fn new(delta_time: f32, key_flags: u32) -> PyTasFrame { + // PyTasFrame::new_from_inner(TasFrame::new(delta_time, key_flags)) + // } + + // #[staticmethod] + // fn with_fps(fps: f32) -> PyResult { + // match TasFrame::with_fps(fps) { + // Ok(frame) => Ok(PyTasFrame::new_from_inner(frame)), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // #[getter] + // fn get_delta_time(&self) -> f32 { + // self.inner.get_delta_time() + // } + + // fn get_fps(&self) -> PyResult { + // match self.inner.get_fps() { + // Ok(fps) => Ok(fps), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn set_delta_time(&mut self, delta_time: f32) { + // self.inner.set_delta_time(delta_time); + // } + + // fn set_fps(&mut self, fps: f32) -> PyResult<()> { + // match self.inner.set_fps(fps) { + // Ok(()) => Ok(()), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn is_key_pressed(&self, key: PyTasKey) -> bool { + // self.inner.is_key_pressed(key.into()) + // } + + // fn set_key_pressed(&mut self, key: PyTasKey, pressed: bool) { + // self.inner.set_key_pressed(key.into(), pressed); + // } + + // fn flip_key_pressed(&mut self, key: PyTasKey) { + // self.inner.flip_key_pressed(key.into()); + // } + + // fn clear_key_pressed(&mut self) { + // self.inner.clear_key_pressed(); + // } + // } + + #[pyclass] + #[derive(Debug)] + struct TasFile { + inner: RsTasFile + } + + #[pymethods] + impl TasFile { + // region: Status + + fn clear(&mut self) -> PyResult<()> { + Ok(self.inner.clear()) + } + + fn get_count(&self) -> PyResult { + Ok(self.inner.get_count()) + } + + fn is_empty(&self) -> PyResult { + Ok(self.inner.is_empty()) + } + + // endregion + + // region: Single Operation + + fn get_delta_time(&self, index: usize) -> PyResult { + Ok(self.inner.visit(index)?.get_delta_time()) + } + + fn get_fps(&self, index: usize) -> PyResult { + Ok(self.inner.visit(index)?.get_fps()?) + } + + fn set_delta_time(&mut self, index: usize, delta_time: f32) -> PyResult<()> { + Ok(self.inner.visit_mut(index)?.set_delta_time(delta_time)) + } + + fn set_fps(&mut self, index: usize, fps: f32) -> PyResult<()> { + Ok(self.inner.visit_mut(index)?.set_fps(fps)?) + } + + fn is_key_pressed(&self, index: usize, key: TasKey) -> PyResult { + Ok(self.inner.visit(index)?.is_key_pressed(key.into())) + } + + fn set_key_pressed(&mut self, index: usize, key: TasKey, pressed: bool) -> PyResult<()> { + Ok(self.inner.visit_mut(index)?.set_key_pressed(key.into(), pressed)) + } + + fn flip_key_pressed(&mut self, index: usize, key: TasKey) -> PyResult<()> { + Ok(self.inner.visit_mut(index)?.flip_key_pressed(key.into())) + } + + fn clear_key_pressed(&mut self, index: usize) -> PyResult<()> { + Ok(self.inner.visit_mut(index)?.clear_key_pressed()) + } + + // endregion + + // region: Batchly Operation + + fn batchly_set_delta_time(&mut self, index_from: usize, index_to: usize, delta_time: f32) -> PyResult<()> { + for frame in self.inner.batchly_visit_mut(index_from, index_to)? { + frame.set_delta_time(delta_time); + } + Ok(()) + } + + fn batchly_set_fps(&mut self, index_from: usize, index_to: usize, fps: f32) -> PyResult<()> { + for frame in self.inner.batchly_visit_mut(index_from, index_to)? { + frame.set_fps(fps)?; + } + Ok(()) + } + + fn batchly_set_key_pressed(&mut self, index_from: usize, index_to: usize, key: TasKey, pressed: bool) -> PyResult<()> { + for frame in self.inner.batchly_visit_mut(index_from, index_to)? { + frame.set_key_pressed(key.into(), pressed); + } + Ok(()) + } + + fn batchly_flip_key_pressed(&mut self, index_from: usize, index_to: usize, key: TasKey) -> PyResult<()> { + for frame in self.inner.batchly_visit_mut(index_from, index_to)? { + frame.flip_key_pressed(key.into()); + } + Ok(()) + } + + fn batchly_clear_key_pressed(&mut self, index_from: usize, index_to: usize) -> PyResult<()> { + for frame in self.inner.batchly_visit_mut(index_from, index_to)? { + frame.clear_key_pressed(); + } + Ok(()) + } + + // endregion + + // region: Modify + + fn append_with_delta_time(&mut self, count: usize, delta_time: f32) -> PyResult<()> { + let frames = vec![RsTasFrame::with_delta_time(delta_time); count]; + Ok(self.inner.append(&frames)) + } + + fn append_with_fps(&mut self, count: usize, fps: f32) -> PyResult<()> { + let frames = vec![RsTasFrame::with_fps(fps)?; count]; + Ok(self.inner.append(&frames)) + } + + fn insert_with_delta_time(&mut self, index: usize, count: usize, delta_time: f32) -> PyResult<()> { + let frames = vec![RsTasFrame::with_delta_time(delta_time); count]; + Ok(self.inner.insert(index, &frames)?) + } + + fn insert_with_fps(&mut self, index: usize, count: usize, fps: f32) -> PyResult<()> { + let frames = vec![RsTasFrame::with_fps(fps)?; count]; + Ok(self.inner.insert(index, &frames)?) + } + + fn remove(&mut self, index_from: usize, index_to: usize) -> PyResult<()> { + Ok(self.inner.remove(index_from, index_to)?) + } + + // endregion + } + + #[pyfunction] + fn create_with_delta_time(count: usize, delta_time: f32) -> PyResult { + Ok(TasFile { inner: RsTasFile::new(vec![RsTasFrame::with_delta_time(delta_time); count]) }) + } + + #[pyfunction] + fn create_with_fps(count: usize, fps: f32) -> PyResult { + Ok(TasFile { inner: RsTasFile::new(vec![RsTasFrame::with_fps(fps)?; count]) }) + } + + #[pyfunction] + fn load(filename: &str) -> PyResult { + Ok(TasFile { inner: RsTasFile::load(filename)? }) + } + + #[pyfunction] + fn save(file: &TasFile, filename: &str) -> PyResult<()> { + Ok(file.inner.save(filename)?) + } + + // #[pyclass] + // pub struct PyTasFile { + // inner: InternalTasFile, + // } + + // // Constructor for PyTasFile + // impl PyTasFile { + // fn new_from_inner(inner: InternalTasFile) -> Self { + // PyTasFile { inner } + // } + // } + + // #[pymethods] + // impl PyTasFile { + // #[new] + // fn new(frames: Option>) -> PyTasFile { + // let frames = frames.unwrap_or_else(|| vec![]); + // let inner_frames = frames.into_iter().map(|f| f.inner).collect(); + // PyTasFile::new_from_inner(InternalTasFile::new(inner_frames)) + // } + + // #[staticmethod] + // fn from_brandnew(count: usize, frame: PyTasFrame) -> PyTasFile { + // PyTasFile::new_from_inner(InternalTasFile::from_brandnew(count, frame.inner)) + // } + + // #[staticmethod] + // fn from_brandnew_with_fps(count: usize, fps: f32) -> PyResult { + // match InternalTasFile::from_brandnew_with_fps(count, fps) { + // Ok(file) => Ok(PyTasFile::new_from_inner(file)), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // #[staticmethod] + // fn load(filename: &str) -> PyResult { + // match InternalTasFile::load(filename) { + // Ok(file) => Ok(PyTasFile::new_from_inner(file)), + // Err(e) => Err(PyErr::new::(e.to_string())), + // } + // } + + // fn save(&self, filename: &str) -> PyResult<()> { + // match self.inner.save(filename) { + // Ok(()) => Ok(()), + // Err(e) => Err(PyErr::new::(e.to_string())), + // } + // } + + // fn clear(&mut self) { + // self.inner.clear(); + // } + + // #[getter] + // fn get_count(&self) -> usize { + // self.inner.get_count() + // } + + // fn is_empty(&self) -> bool { + // self.inner.is_empty() + // } + + // fn visit(&self, index: usize) -> PyResult { + // match self.inner.visit(index) { + // Ok(frame) => Ok(PyTasFrame::new_from_inner(*frame)), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn visit_mut(&mut self, index: usize) -> PyResult { + // match self.inner.visit_mut(index) { + // Ok(frame) => Ok(PyTasFrame::new_from_inner((*frame).clone())), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn batchly_visit(&self, index_from: usize, index_to: usize) -> PyResult> { + // match self.inner.batchly_visit(index_from, index_to) { + // Ok(frames) => { + // let py_frames: Vec = frames + // .iter() + // .map(|f| PyTasFrame::new_from_inner(*f)) + // .collect(); + // Ok(py_frames) + // } + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn batchly_visit_mut( + // &mut self, + // index_from: usize, + // index_to: usize, + // ) -> PyResult> { + // match self.inner.batchly_visit_mut(index_from, index_to) { + // Ok(frames) => { + // let py_frames: Vec = frames + // .iter() + // .map(|f| PyTasFrame::new_from_inner((*f).clone())) + // .collect(); + // Ok(py_frames) + // } + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn append(&mut self, frames: Vec) { + // let inner_frames: Vec = frames.into_iter().map(|f| f.inner).collect(); + // self.inner.append(&inner_frames); + // } + + // fn insert(&mut self, index: usize, frames: Vec) -> PyResult<()> { + // let inner_frames: Vec = frames.into_iter().map(|f| f.inner).collect(); + // match self.inner.insert(index, &inner_frames) { + // Ok(()) => Ok(()), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + + // fn remove(&mut self, index_from: usize, index_to: usize) -> PyResult<()> { + // match self.inner.remove(index_from, index_to) { + // Ok(()) => Ok(()), + // Err(e) => Err(PyErr::new::( + // e.to_string(), + // )), + // } + // } + // } } diff --git a/BallanceTasSonnet/src/tasfile.rs b/BallanceTasSonnet/src/tasfile.rs deleted file mode 100644 index 87f88cc..0000000 --- a/BallanceTasSonnet/src/tasfile.rs +++ /dev/null @@ -1,7 +0,0 @@ -use pyo3::prelude::*; - -/// Formats the sum of two numbers as string. -#[pyfunction] -fn sum_as_string(a: usize, b: usize) -> PyResult { - Ok((a + b).to_string()) -} \ No newline at end of file diff --git a/BallanceTasSonnet/src/wrapped/tasfile.rs b/BallanceTasSonnet/src/wrapped/tasfile.rs index eb81e0a..9754196 100644 --- a/BallanceTasSonnet/src/wrapped/tasfile.rs +++ b/BallanceTasSonnet/src/wrapped/tasfile.rs @@ -30,7 +30,7 @@ pub enum Error { type Result = std::result::Result; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum TasKey { KeyUp, KeyDown, @@ -58,8 +58,12 @@ impl TasFrame { } } + pub fn with_delta_time(delta_time: f32) -> Self { + Self::new(delta_time, 0u32) + } + pub fn with_fps(fps: f32) -> Result { - Ok(Self::new(Self::to_delta_time(fps)?, 0u32)) + Ok(Self::with_delta_time(Self::to_delta_time(fps)?)) } } @@ -144,14 +148,6 @@ impl TasFile { Self { frames } } - pub fn from_brandnew(count: usize, frame: TasFrame) -> Self { - Self::new(vec![frame; count]) - } - - pub fn from_brandnew_with_fps(count: usize, fps: f32) -> Result { - Ok(Self::from_brandnew(count, TasFrame::with_fps(fps)?)) - } - pub fn load(filename: &str) -> Result { // Open file let mut reader = File::open(filename)?;