Skip to main content

pit_rust_generic/
lib.rs

1use pit_core::{Arg, Interface, Sig};
2use proc_macro2::TokenStream;
3use quote::{format_ident, quote};
4use syn::token::Async;
5pub struct Params {
6    pub core: syn::Path,
7    pub flags: FeatureFlags,
8    pub asyncness: Option<Async>,
9}
10#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
11#[non_exhaustive]
12pub struct FeatureFlags {}
13pub fn arg(p: &Params, a: &Arg, root: [u8; 32]) -> TokenStream {
14    let core = &p.core;
15    let asyncness = &p.asyncness;
16    match a {
17        Arg::I32 => quote! {#core::primitive::u32},
18        Arg::I64 => quote! {#core::primitive::u64},
19        Arg::F32 => quote! {#core::primitive::f32},
20        Arg::F64 => quote! {#core::primitive::f64},
21        Arg::Resource {
22            ty,
23            nullable,
24            take,
25            ann,
26        } => {
27            let x = match ty {
28                pit_core::ResTy::None => {
29                    return quote! {
30                        impl #core::any::Any + 'bound
31                    };
32                }
33                pit_core::ResTy::Of(a) => *a,
34                pit_core::ResTy::This => root,
35                _ => {
36                    return quote! {
37                        #core::convert::Infallible
38                    };
39                }
40            };
41            let x = hex::encode(&x);
42            let x = format_ident!(
43                "P{}{x}",
44                match asyncness.as_ref() {
45                    None => "",
46                    Some(_) => "async",
47                }
48            );
49            let mut a = quote! {
50                impl #x<'bound,Error = Self::Error> + 'bound
51            };
52            if !*take {
53                a = quote! {
54                    impl #core::ops::DerefMut<Target = #a> + 'bound
55                }
56            }
57            if *nullable {
58                a = quote! {
59                    #core::option::Option<#a>
60                }
61            }
62            a
63        }
64        _ => quote! {
65            #core::convert::Infallible
66        },
67    }
68}
69pub fn sig(p: &Params, s: &Sig, root: [u8; 32]) -> TokenStream {
70    let params = s.params.iter().enumerate().map(|(a, b)| {
71        let a = format_ident!("arg{a}");
72        let b = arg(p, b, root);
73        quote! {
74            #a : #b
75        }
76    });
77    let rets = s.rets.iter().map(|a| arg(p, a, root));
78    let core = &p.core;
79    quote! {
80        (&mut self, #(#params),*) -> #core::result::Result<(#(#rets),*),Self::Error>
81    }
82}
83pub fn interface(p: &Params, i: &Interface) -> TokenStream {
84    let root = i.rid();
85    let asyncness = &p.asyncness;
86    let x = hex::encode(&root);
87    let x = format_ident!(
88        "P{}{x}",
89        match asyncness.as_ref() {
90            None => "",
91            Some(_) => "async",
92        }
93    );
94    let core = &p.core;
95
96    let methods = i.methods.iter().map(|(a, b)| {
97        let asyncness = asyncness.iter();
98        let a = format_ident!("{a}");
99        let b = sig(p, b, root);
100        quote! {
101            #(#asyncness)* fn  #a #b
102        }
103    });
104    quote! {
105        trait #x<'bound>: 'bound{
106            type Error: #core::error::Error;
107            #(#methods);*
108        }
109    }
110}