pub fn struct_member(id: &Id) -> Ident
Expand description

Convert a struct member from its Id name to its Rust Ident representation.

Examples found in repository?
src/types/record.rs (line 13)
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
pub(super) fn define_struct(name: &witx::Id, s: &witx::RecordDatatype) -> TokenStream {
    let ident = names::type_(name);
    let size = s.mem_size_align().size as u32;
    let align = s.mem_size_align().align as usize;

    let member_names = s.members.iter().map(|m| names::struct_member(&m.name));
    let member_decls = s.members.iter().map(|m| {
        let name = names::struct_member(&m.name);
        let type_ = match &m.tref {
            witx::TypeRef::Name(nt) => {
                let tt = names::type_(&nt.name);
                if m.tref.needs_lifetime() {
                    quote!(#tt<'a>)
                } else {
                    quote!(#tt)
                }
            }
            witx::TypeRef::Value(ty) => match &**ty {
                witx::Type::Builtin(builtin) => names::builtin_type(*builtin),
                witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => {
                    let pointee_type = names::type_ref(&pointee, quote!('a));
                    quote!(wiggle::GuestPtr<'a, #pointee_type>)
                }
                _ => unimplemented!("other anonymous struct members: {:?}", m.tref),
            },
        };
        quote!(pub #name: #type_)
    });

    let member_reads = s.member_layout().into_iter().map(|ml| {
        let name = names::struct_member(&ml.member.name);
        let offset = ml.offset as u32;
        let location = quote!(location.cast::<u8>().add(#offset)?.cast());
        match &ml.member.tref {
            witx::TypeRef::Name(nt) => {
                let type_ = names::type_(&nt.name);
                quote! {
                    let #name = <#type_ as wiggle::GuestType>::read(&#location)?;
                }
            }
            witx::TypeRef::Value(ty) => match &**ty {
                witx::Type::Builtin(builtin) => {
                    let type_ = names::builtin_type(*builtin);
                    quote! {
                        let #name = <#type_ as wiggle::GuestType>::read(&#location)?;
                    }
                }
                witx::Type::Pointer(pointee) | witx::Type::ConstPointer(pointee) => {
                    let pointee_type = names::type_ref(&pointee, anon_lifetime());
                    quote! {
                        let #name = <wiggle::GuestPtr::<#pointee_type> as wiggle::GuestType>::read(&#location)?;
                    }
                }
                _ => unimplemented!("other anonymous struct members: {:?}", ty),
            },
        }
    });

    let member_writes = s.member_layout().into_iter().map(|ml| {
        let name = names::struct_member(&ml.member.name);
        let offset = ml.offset as u32;
        quote! {
            wiggle::GuestType::write(
                &location.cast::<u8>().add(#offset)?.cast(),
                val.#name,
            )?;
        }
    });

    let (struct_lifetime, extra_derive) = if s.needs_lifetime() {
        (quote!(<'a>), quote!())
    } else {
        (quote!(), quote!(, PartialEq))
    };

    quote! {
        #[derive(Clone, Debug #extra_derive)]
        pub struct #ident #struct_lifetime {
            #(#member_decls),*
        }

        impl<'a> wiggle::GuestType<'a> for #ident #struct_lifetime {
            fn guest_size() -> u32 {
                #size
            }

            fn guest_align() -> usize {
                #align
            }

            fn read(location: &wiggle::GuestPtr<'a, Self>) -> Result<Self, wiggle::GuestError> {
                #(#member_reads)*
                Ok(#ident { #(#member_names),* })
            }

            fn write(location: &wiggle::GuestPtr<'_, Self>, val: Self) -> Result<(), wiggle::GuestError> {
                #(#member_writes)*
                Ok(())
            }
        }
    }
}