babys first rust
This commit is contained in:
parent
22c08c7627
commit
84d1049b7d
10 changed files with 3326 additions and 0 deletions
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "sryaml"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
pyo3 = { version = "0.20.3", features = ["extension-module", "serde"] }
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_yaml = "0.9.32"
|
||||
|
||||
|
||||
[profile.release-lto]
|
||||
inherits = "release"
|
||||
lto = true
|
||||
|
||||
[lib]
|
||||
# See https://github.com/PyO3/pyo3 for details
|
||||
name = "_sryamllib" # private module to be nested into Python package
|
||||
crate-type = ["cdylib"]
|
||||
path = "src/rust/lib.rs"
|
2
MANIFEST.in
Normal file
2
MANIFEST.in
Normal file
|
@ -0,0 +1,2 @@
|
|||
include Cargo.toml
|
||||
recursive-include src/rust *.rs
|
|
@ -1,2 +1,10 @@
|
|||
# serde-yaml-python
|
||||
|
||||
|
||||
|
||||
## Resources
|
||||
|
||||
Stuff i gone and learned from
|
||||
|
||||
- https://rust.code-maven.com/read-arbitrary-yaml
|
||||
- https://stackoverflow.com/questions/70193869/exporting-hashmap-of-hashmap-to-python
|
1
build-wheels.sh
Executable file
1
build-wheels.sh
Executable file
|
@ -0,0 +1 @@
|
|||
ARCHFLAGS="-arch x86_64 -arch arm64" python -m build
|
17
pyproject.toml
Normal file
17
pyproject.toml
Normal file
|
@ -0,0 +1,17 @@
|
|||
[build-system]
|
||||
requires = ["setuptools", "setuptools-rust"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "sryaml"
|
||||
version = "0.1.0"
|
||||
|
||||
[tool.setuptools.packages]
|
||||
find = { where= ["src"]}
|
||||
|
||||
[[tool.setuptools-rust.ext-modules]]
|
||||
target = "sryaml._sryamllib"
|
||||
binding = "PyO3" # Default value, can be omitted
|
||||
|
||||
[bdist_wheel]
|
||||
py_limited_api= "cp38" # replace with desired minimum Python version
|
68
src/rust/lib.rs
Normal file
68
src/rust/lib.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use pyo3::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn to_python(v: &serde_yaml::Value, py: Python<'_> ) -> PyObject {
|
||||
match v {
|
||||
serde_yaml::Value::Null => py.None(),
|
||||
serde_yaml::Value::Bool(s) => s.to_object(py),
|
||||
serde_yaml::Value::Number(s) => {
|
||||
let oi64 = s.as_i64().map( |i| i.to_object( py ) );
|
||||
let ou64 = s.as_u64().map( |i| i.to_object( py ) );
|
||||
let of64 = s.as_f64().map( |i| i.to_object( py ) );
|
||||
oi64.or( ou64 ).or( of64 ).expect( "number too large" )
|
||||
},
|
||||
serde_yaml::Value::String(s) => s.to_object(py),
|
||||
serde_yaml::Value::Sequence(s) => {
|
||||
let inner: Vec<_> = s.iter().map(|x| to_python(x, py)).collect();
|
||||
inner.to_object( py )
|
||||
}
|
||||
serde_yaml::Value::Mapping(s) => {
|
||||
// FIXME: This required a hack of casting the key to a string, idk what i'm doing here lmao
|
||||
let inner : HashMap<_, _>= s.into_iter()
|
||||
.map( |( k, v )| ( k.as_str(), to_python( v, py ) ) ).collect();
|
||||
inner.to_object(py)
|
||||
},
|
||||
serde_yaml::Value::Tagged(_s) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive( Clone, Debug )]
|
||||
struct ParsedValue( serde_yaml::Value );
|
||||
|
||||
impl ToPyObject for ParsedValue {
|
||||
fn to_object( &self, py: Python<'_> ) -> PyObject {
|
||||
to_python( &self.0, py )
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn loads(text: &str) -> PyResult<String>{
|
||||
Ok(text.to_string())
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn load(path: &str, py: Python) -> PyResult<Py<PyAny>>{
|
||||
let parsed: serde_yaml::Value = match std::fs::File::open(path) {
|
||||
Ok(file) => match serde_yaml::from_reader(file) {
|
||||
Ok(data) => data,
|
||||
Err(err) => {
|
||||
eprintln!("There was an error parsing the YAML file {}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
Err(error) => {
|
||||
eprintln!("Error opening file {}: {}", path, error);
|
||||
std::process::exit(1)
|
||||
}
|
||||
};
|
||||
Ok(to_python(&parsed, py))
|
||||
}
|
||||
|
||||
#[pymodule]
|
||||
fn _sryamllib(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_pyfunction!(loads, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(load, m)?)?;
|
||||
Ok(())
|
||||
}
|
1
src/sryaml/__init__.py
Normal file
1
src/sryaml/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
from ._sryamllib import loads, load
|
2
tests/data/basic.yaml
Normal file
2
tests/data/basic.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
mydict:
|
||||
what
|
3195
tests/data/meta.yaml
Normal file
3195
tests/data/meta.yaml
Normal file
File diff suppressed because it is too large
Load diff
10
tests/test_time.py
Normal file
10
tests/test_time.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
import timeit
|
||||
from yaml import (load as yload, Loader)
|
||||
import sryaml
|
||||
|
||||
metamodel = 'data/meta.yaml'
|
||||
pyyaml_time = timeit.timeit("yload(metamodel, Loader=Loader)", globals=globals(), number=1000)
|
||||
sryaml_time = timeit.timeit("sryaml.load(metamodel)", globals=globals(), number=1000)
|
||||
|
||||
print(f"pyyaml time: {pyyaml_time}")
|
||||
print(f"sryaml time: {sryaml_time}")
|
Loading…
Reference in a new issue