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}