From eb6efd2b3d574e63952f49f54f330e0d629cfa87 Mon Sep 17 00:00:00 2001 From: Jason Colburne Date: Sat, 4 Feb 2023 11:11:55 -0400 Subject: [PATCH] python ffi --- .gitignore | 4 +- Makefile | 33 ++++++++++++++ cargo/python/.cargo/config.toml | 11 +++++ cargo/python/Cargo.toml.tail | 11 +++++ src/core/counter/mod.rs | 2 +- src/core/diger.rs | 2 +- src/core/matter/mod.rs | 9 ++-- src/core/mod.rs | 12 +++--- src/lib.rs | 7 +++ src/lib_python.rs | 16 +++++++ src/python/matter.rs | 76 +++++++++++++++++++++++++++++++++ src/python/mod.rs | 1 + 12 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 Makefile create mode 100644 cargo/python/.cargo/config.toml create mode 100644 cargo/python/Cargo.toml.tail create mode 100644 src/lib_python.rs create mode 100644 src/python/matter.rs create mode 100644 src/python/mod.rs diff --git a/.gitignore b/.gitignore index 6a4b33d..044eef8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /target /Cargo.lock +/cargo/*/Cargo.toml +/cargo/*/Cargo.lock /*.profraw -.idea \ No newline at end of file +.idea diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..52c3a3f --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +DEV_DEPENDENCIES_LINE = $(shell cat Cargo.toml | grep -n "\[dev-dependencies\]" | cut -d : -f 1) +DELIMITING_LINE = $(shell echo $$(( $(DEV_DEPENDENCIES_LINE) - 2 ))) +TOTAL_LINES = $(shell cat Cargo.toml | wc -l) +TAIL_LINES = $(shell echo $$(( $(TOTAL_LINES) - $(DELIMITING_LINE) ))) + +python: + @head -n $(DELIMITING_LINE) Cargo.toml > cargo/$@/Cargo.toml + @echo "pyo3 = { version = \"0.18.0\", features = [\"abi3\", \"extension-module\"] }" >> cargo/$@/Cargo.toml + @tail -n $(TAIL_LINES) Cargo.toml >> cargo/$@/Cargo.toml + @echo >> cargo/$@/Cargo.toml + @cat cargo/$@/Cargo.toml.tail >> cargo/$@/Cargo.toml + @cd cargo/$@ && cargo build --release --target-dir ../../target/$@ + @mv target/$@/release/libcesride.dylib target/$@/release/cesride.so + +python-shell: + @cd target/python/release/ && python3 + +rust: + @cargo build --release + +libs: rust python + +clean: + cargo clean + +preflight: + cargo fmt + cargo fix + cargo clippy -- -D warnings + cargo build --release + cargo test --release + cargo audit + cargo tarpaulin diff --git a/cargo/python/.cargo/config.toml b/cargo/python/.cargo/config.toml new file mode 100644 index 0000000..d47f983 --- /dev/null +++ b/cargo/python/.cargo/config.toml @@ -0,0 +1,11 @@ +[target.x86_64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] + +[target.aarch64-apple-darwin] +rustflags = [ + "-C", "link-arg=-undefined", + "-C", "link-arg=dynamic_lookup", +] diff --git a/cargo/python/Cargo.toml.tail b/cargo/python/Cargo.toml.tail new file mode 100644 index 0000000..e8b6050 --- /dev/null +++ b/cargo/python/Cargo.toml.tail @@ -0,0 +1,11 @@ +[lib] +path = "../../src/lib_python.rs" +test = false +doctest = false +bench = true +doc = true +crate-type = ["cdylib"] + +[features] +default = ["python"] +python = [] diff --git a/src/core/counter/mod.rs b/src/core/counter/mod.rs index cd943ec..f57638b 100644 --- a/src/core/counter/mod.rs +++ b/src/core/counter/mod.rs @@ -1,4 +1,4 @@ -pub(crate) mod tables; +pub mod tables; use crate::core::util; use crate::error::{err, Error, Result}; diff --git a/src/core/diger.rs b/src/core/diger.rs index 4fdc1ff..954ae9f 100644 --- a/src/core/diger.rs +++ b/src/core/diger.rs @@ -5,7 +5,7 @@ use crate::error::{err, Error, Result}; type Blake2b256 = blake2::Blake2b; -trait Diger { +pub trait Diger { fn new_with_code_and_raw(code: &str, raw: &[u8]) -> Result where Self: Sized; diff --git a/src/core/matter/mod.rs b/src/core/matter/mod.rs index bf160f7..0f3d3a8 100644 --- a/src/core/matter/mod.rs +++ b/src/core/matter/mod.rs @@ -1,10 +1,13 @@ -pub(crate) mod tables; - use base64::{engine::general_purpose as b64_engine, Engine}; +#[cfg(feature = "python")] +use pyo3::prelude::pyclass; use crate::core::util; use crate::error::{err, Error, Result}; +pub mod tables; + +#[cfg_attr(feature = "python", pyclass)] #[derive(Debug, Clone)] pub struct Matter { pub(crate) raw: Vec, @@ -131,8 +134,6 @@ impl Matter { self.binfil() } - pub fn transferable() {} - fn infil(&self) -> Result { let code = &self.code; let size = self.size; diff --git a/src/core/mod.rs b/src/core/mod.rs index 0c02d6e..be33f99 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,6 +1,6 @@ -mod cigar; -mod counter; -mod diger; -mod matter; -mod util; -mod verfer; +pub mod cigar; +pub mod counter; +pub mod diger; +pub mod matter; +pub mod util; +pub mod verfer; diff --git a/src/lib.rs b/src/lib.rs index de0eea5..0578eee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,3 +3,10 @@ mod core; mod error; + +pub use crate::core::cigar::Cigar; +pub use crate::core::counter::{tables as counter, Counter}; +pub use crate::core::diger::Diger; +pub use crate::core::matter::{tables as matter, Matter}; +pub use crate::core::util; +pub use crate::core::verfer::Verfer; diff --git a/src/lib_python.rs b/src/lib_python.rs new file mode 100644 index 0000000..b6d88cf --- /dev/null +++ b/src/lib_python.rs @@ -0,0 +1,16 @@ +// TODO: remove before 1.0.0 +#![allow(dead_code)] + +use pyo3::prelude::*; + +mod core; +mod error; +mod python; + +use crate::core::matter::Matter; + +#[pymodule] +fn cesride(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} diff --git a/src/python/matter.rs b/src/python/matter.rs new file mode 100644 index 0000000..85edcd9 --- /dev/null +++ b/src/python/matter.rs @@ -0,0 +1,76 @@ +use pyo3::{ + prelude::*, + exceptions::{PyException, PyValueError}, +}; + +use crate::core::matter::Matter; + +#[pymethods] +impl Matter { + #[new] + fn py_new( + code: Option<&str>, + raw: Option<&[u8]>, + raw_size: Option, + qb64: Option<&str>, + qb64b: Option<&[u8]>, + qb2: Option<&[u8]>, + ) -> PyResult { + let result = if let Some(code) = code { + let (raw, raw_size) = if raw.is_none() || raw_size.is_none() { + return Err(PyValueError::new_err("code present, raw and raw_size missing")); + } else { + (raw.unwrap(), raw_size.unwrap()) + }; + + Self::new_with_code_and_raw(code, raw, raw_size) + } else if let Some(qb64) = qb64 { + Self::new_with_qb64(qb64) + } else if let Some(qb64b) = qb64b { + Self::new_with_qb64b(qb64b) + } else if let Some(qb2) = qb2 { + Self::new_with_qb2(qb2) + } else { + return Err(PyValueError::new_err("must specify some parameters")); + }; + + match result { + Ok(matter) => Ok(matter), + Err(e) => Err(PyException::new_err(e.to_string())), + } + } + + #[pyo3(name = "code")] + fn py_code(&self) -> String { + self.code() + } + + #[pyo3(name = "raw")] + fn py_raw(&self) -> Vec { + self.raw() + } + + #[pyo3(name = "qb64")] + fn py_qb64(&self) -> PyResult { + match self.qb64() { + Ok(s) => Ok(s), + Err(e) => Err(PyException::new_err(e.to_string())), + } + } + + #[pyo3(name = "qb64b")] + fn py_qb64b(&self) -> PyResult> { + match self.qb64b() { + Ok(b) => Ok(b), + Err(e) => Err(PyException::new_err(e.to_string())), + } + } + + #[pyo3(name = "qb2")] + fn py_qb2(&self) -> PyResult> { + match self.qb2() { + Ok(b) => Ok(b), + Err(e) => Err(PyException::new_err(e.to_string())), + } + } +} diff --git a/src/python/mod.rs b/src/python/mod.rs new file mode 100644 index 0000000..62890b8 --- /dev/null +++ b/src/python/mod.rs @@ -0,0 +1 @@ +mod matter; \ No newline at end of file