obi_derive_internal/
struct_enc.rs1use proc_macro2::{Span, TokenStream};
2use quote::quote;
3use syn::{Fields, Index, ItemStruct};
4
5pub fn struct_enc(input: &ItemStruct) -> syn::Result<TokenStream> {
6 let name = &input.ident;
7 let generics = &input.generics;
8 let mut body = TokenStream::new();
9 let mut encode_field_types = TokenStream::new();
10 match &input.fields {
11 Fields::Named(fields) => {
12 for field in &fields.named {
13 let field_name = field.ident.as_ref().unwrap();
14 let delta = quote! {
15 obi::OBIEncode::encode(&self.#field_name, writer)?;
16 };
17 body.extend(delta);
18
19 let field_type = &field.ty;
20 encode_field_types.extend(quote! {
21 #field_type: obi::enc::OBIEncode,
22 });
23 }
24 }
25 Fields::Unnamed(fields) => {
26 for field_idx in 0..fields.unnamed.len() {
27 let field_idx = Index {
28 index: field_idx as u32,
29 span: Span::call_site(),
30 };
31 let delta = quote! {
32 obi::OBIEncode::encode(&self.#field_idx, writer)?;
33 };
34 body.extend(delta);
35 }
36 }
37 Fields::Unit => {}
38 }
39 Ok(quote! {
40 impl #generics obi::enc::OBIEncode for #name #generics where #encode_field_types {
41 fn encode<W: std::io::Write>(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> {
42 #body
43 Ok(())
44 }
45 }
46 })
47}
48
49#[rustfmt::skip]
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 fn assert_eq(expected: TokenStream, actual: TokenStream) {
56 assert_eq!(expected.to_string(), actual.to_string())
57 }
58
59 #[test]
60 fn simple_struct() {
61 let item_struct: ItemStruct = syn::parse2(quote!{
62 struct A {
63 x: u64,
64 y: String,
65 }
66 }).unwrap();
67
68 let actual = struct_enc(&item_struct).unwrap();
69 let expected = quote!{
70 impl obi::enc::OBIEncode for A
71 where
72 u64: obi::enc::OBIEncode,
73 String: obi::enc::OBIEncode,
74 {
75 fn encode<W: std::io::Write>(&self, writer: &mut W) -> std::result::Result<(), std::io::Error> {
76 obi::OBIEncode::encode(&self.x, writer)?;
77 obi::OBIEncode::encode(&self.y, writer)?;
78 Ok(())
79 }
80 }
81 };
82 assert_eq(expected, actual);
83 }
84}