Skip to content

Commit 9dc7f20

Browse files
stephenh-axiom-xyzjonathanpwang
authored andcommitted
feat: Encode + Decode trait definition and Proof implementation (#206)
1 parent 59dadfc commit 9dc7f20

File tree

6 files changed

+787
-3
lines changed

6 files changed

+787
-3
lines changed

crates/stark-backend-v2/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ description = "Proof system v2"
88
[dependencies]
99
openvm-stark-backend.workspace = true
1010
openvm-stark-sdk.workspace = true
11+
codec-derive.workspace = true
1112

1213
p3-air.workspace = true
1314
p3-baby-bear.workspace = true
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "codec-derive"
3+
description = "Procedural macros for encoding and decoding."
4+
version.workspace = true
5+
authors.workspace = true
6+
edition.workspace = true
7+
8+
[lib]
9+
proc-macro = true
10+
11+
[dependencies]
12+
quote = "1.0"
13+
syn = { version = "2.0", features = ["parsing", "full"] }
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use proc_macro::TokenStream;
2+
use quote::quote;
3+
use syn::{Data, DeriveInput, Fields, parse_macro_input};
4+
5+
#[proc_macro_derive(Encode)]
6+
pub fn encode_derive(input: TokenStream) -> TokenStream {
7+
let ast = parse_macro_input!(input as DeriveInput);
8+
let name = &ast.ident;
9+
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
10+
11+
let fields = match &ast.data {
12+
Data::Struct(data_struct) => &data_struct.fields,
13+
Data::Enum(_) => {
14+
return syn::Error::new(
15+
name.span(),
16+
"Encode derive macro only supports structs, not enums",
17+
)
18+
.to_compile_error()
19+
.into();
20+
}
21+
Data::Union(_) => {
22+
return syn::Error::new(
23+
name.span(),
24+
"Encode derive macro only supports structs, not unions",
25+
)
26+
.to_compile_error()
27+
.into();
28+
}
29+
};
30+
31+
let encode_fields = match fields {
32+
Fields::Named(fields_named) => {
33+
let field_encodes = fields_named.named.iter().map(|field| {
34+
let field_name = &field.ident;
35+
quote! {
36+
self.#field_name.encode(writer)?;
37+
}
38+
});
39+
quote! {
40+
#(#field_encodes)*
41+
}
42+
}
43+
Fields::Unnamed(fields_unnamed) => {
44+
let field_encodes = fields_unnamed.unnamed.iter().enumerate().map(|(idx, _)| {
45+
let index = syn::Index::from(idx);
46+
quote! {
47+
self.#index.encode(writer)?;
48+
}
49+
});
50+
quote! {
51+
#(#field_encodes)*
52+
}
53+
}
54+
Fields::Unit => {
55+
quote! {}
56+
}
57+
};
58+
59+
let expanded = quote! {
60+
impl #impl_generics crate::codec::Encode for #name #type_generics #where_clause {
61+
fn encode<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
62+
#encode_fields
63+
Ok(())
64+
}
65+
}
66+
};
67+
68+
TokenStream::from(expanded)
69+
}
70+
71+
#[proc_macro_derive(Decode)]
72+
pub fn decode_derive(input: TokenStream) -> TokenStream {
73+
let ast = parse_macro_input!(input as DeriveInput);
74+
let name = &ast.ident;
75+
let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl();
76+
77+
let fields = match &ast.data {
78+
Data::Struct(data_struct) => &data_struct.fields,
79+
Data::Enum(_) => {
80+
return syn::Error::new(
81+
name.span(),
82+
"Decode derive macro only supports structs, not enums",
83+
)
84+
.to_compile_error()
85+
.into();
86+
}
87+
Data::Union(_) => {
88+
return syn::Error::new(
89+
name.span(),
90+
"Decode derive macro only supports structs, not unions",
91+
)
92+
.to_compile_error()
93+
.into();
94+
}
95+
};
96+
97+
let decode_fields = match fields {
98+
Fields::Named(fields_named) => {
99+
let field_decodes = fields_named.named.iter().map(|field| {
100+
let field_name = &field.ident;
101+
let field_ty = &field.ty;
102+
quote! {
103+
#field_name: <#field_ty as crate::codec::Decode>::decode(reader)?,
104+
}
105+
});
106+
quote! {
107+
{
108+
#(#field_decodes)*
109+
}
110+
}
111+
}
112+
Fields::Unnamed(fields_unnamed) => {
113+
let field_decodes = fields_unnamed.unnamed.iter().map(|field| {
114+
let field_ty = &field.ty;
115+
quote! {
116+
<#field_ty as crate::codec::Decode>::decode(reader)?,
117+
}
118+
});
119+
quote! {
120+
(
121+
#(#field_decodes)*
122+
)
123+
}
124+
}
125+
Fields::Unit => {
126+
quote! {}
127+
}
128+
};
129+
130+
let expanded = quote! {
131+
impl #impl_generics crate::codec::Decode for #name #type_generics #where_clause {
132+
fn decode<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
133+
Ok(Self #decode_fields)
134+
}
135+
}
136+
};
137+
138+
TokenStream::from(expanded)
139+
}

0 commit comments

Comments
 (0)