feat: FromPyFromStr and ToStrToPy macros YAY
This commit is contained in:
@@ -4,6 +4,6 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.106"
|
||||
quote = "1.0.46"
|
||||
syn = "2.0.118"
|
||||
proc-macro2 = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true }
|
||||
|
||||
56
python-utils-macros-impl/src/from_py_from_str.rs
Normal file
56
python-utils-macros-impl/src/from_py_from_str.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, quote};
|
||||
use syn::{
|
||||
DeriveInput, GenericParam,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_quote,
|
||||
};
|
||||
|
||||
pub struct FromPyFromStr {
|
||||
derive_input: DeriveInput,
|
||||
}
|
||||
|
||||
impl Parse for FromPyFromStr {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let derive_input = input.parse()?;
|
||||
|
||||
let this = Self { derive_input };
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for FromPyFromStr {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let name = &self.derive_input.ident;
|
||||
|
||||
let (_, ty_generics, where_clause) = self.derive_input.generics.split_for_impl();
|
||||
let mut generics = self.derive_input.generics.clone();
|
||||
|
||||
let a_lifetime: GenericParam = parse_quote!('a);
|
||||
let py_lifetime: GenericParam = parse_quote!('py);
|
||||
|
||||
generics.params.push(a_lifetime.clone());
|
||||
generics.params.push(py_lifetime.clone());
|
||||
|
||||
let (impl_generics, _, _) = generics.split_for_impl();
|
||||
|
||||
let output = quote! {
|
||||
impl #impl_generics ::pyo3::conversion::FromPyObject<#a_lifetime, #py_lifetime> for #name #ty_generics #where_clause
|
||||
where
|
||||
#name #ty_generics: ::std::str::FromStr,
|
||||
<#name #ty_generics as ::std::str::FromStr>::Err: ::std::fmt::Display,
|
||||
{
|
||||
type Error = ::python_utils::ExtractPyObjectViaParseError<<#name #ty_generics as ::std::str::FromStr>::Err>;
|
||||
|
||||
fn extract(obj: ::pyo3::Borrowed<#a_lifetime, #py_lifetime, ::pyo3::types::PyAny>) -> ::core::result::Result<Self, Self::Error> {
|
||||
::python_utils::FromPyObjectViaParse::extract(obj).map(|wrapper| wrapper.0)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dbg!(&output.to_string());
|
||||
|
||||
tokens.extend(output);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,5 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{DeriveInput, parse_macro_input};
|
||||
mod from_py_from_str;
|
||||
mod to_str_to_py;
|
||||
|
||||
pub fn py_from_str(input: TokenStream) -> TokenStream {
|
||||
let derive_input: DeriveInput = parse_macro_input!(input);
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics MyTrait for #name #ty_generics #where_clause {
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
expanded
|
||||
}
|
||||
pub use from_py_from_str::FromPyFromStr;
|
||||
pub use to_str_to_py::ToStrToPy;
|
||||
|
||||
56
python-utils-macros-impl/src/to_str_to_py.rs
Normal file
56
python-utils-macros-impl/src/to_str_to_py.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{ToTokens, quote};
|
||||
use syn::{
|
||||
DeriveInput, GenericParam,
|
||||
parse::{Parse, ParseStream},
|
||||
parse_quote,
|
||||
};
|
||||
|
||||
pub struct ToStrToPy {
|
||||
derive_input: DeriveInput,
|
||||
}
|
||||
|
||||
impl Parse for ToStrToPy {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let derive_input = input.parse()?;
|
||||
|
||||
let this = Self { derive_input };
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ToStrToPy {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let name = &self.derive_input.ident;
|
||||
|
||||
let (_, ty_generics, where_clause) = self.derive_input.generics.split_for_impl();
|
||||
let mut generics = self.derive_input.generics.clone();
|
||||
|
||||
let py_lifetime: GenericParam = parse_quote!('py);
|
||||
|
||||
generics.params.push(py_lifetime.clone());
|
||||
|
||||
let (impl_generics, _, _) = generics.split_for_impl();
|
||||
|
||||
let output = quote! {
|
||||
impl #impl_generics ::pyo3::conversion::IntoPyObject<#py_lifetime> for #name #ty_generics #where_clause
|
||||
where
|
||||
#name #ty_generics: ::std::fmt::Display
|
||||
{
|
||||
type Target = ::pyo3::types::PyString;
|
||||
type Output = ::pyo3::Bound<#py_lifetime, Self::Target>;
|
||||
type Error = ::std::convert::Infallible;
|
||||
|
||||
fn into_pyobject(self, py: ::pyo3::Python<#py_lifetime>) -> ::core::result::Result<Self::Output, Self::Error> {
|
||||
let s = ::std::string::ToString::to_string(&self);
|
||||
::pyo3::conversion::IntoPyObject::into_pyobject(s, py)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dbg!(&output.to_string());
|
||||
|
||||
tokens.extend(output);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user