1
2
3
4
5
6
7
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
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::{parse2, Field, Generics};

use crate::ATTR_RAW;

pub(crate) struct WrappedRawStructInfo {
    pub struct_ident: Ident,
    pub struct_generics: Generics,
    pub raw_field: Field,
    pub other_fields: Vec<Field>,
}

impl Parse for WrappedRawStructInfo {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        match crate::parse_wrapped_struct_info(input, ATTR_RAW) {
            Ok((struct_ident, struct_generics, raw_field, other_fields)) => {
                Ok(WrappedRawStructInfo {
                    struct_ident,
                    struct_generics,
                    raw_field,
                    other_fields,
                })
            }
            Err(error) => Err(error),
        }
    }
}

pub fn derive_raw_wrapper(input: TokenStream) -> TokenStream {
    let struct_info = match parse2::<WrappedRawStructInfo>(input) {
        Ok(parsed) => parsed,
        Err(error) => return error.to_compile_error(),
    };

    let struct_ident = &struct_info.struct_ident;
    let raw_field_ident = &struct_info.raw_field.ident;
    let raw_field_type = &struct_info.raw_field.ty;
    let other_fields_idents: Vec<&Ident> = struct_info
        .other_fields
        .iter()
        .map(|f| {
            f.ident
                .as_ref()
                .expect("Anonymous fields are not supported")
        })
        .collect();

    let mut struct_generics_without_default = struct_info.struct_generics.clone();
    crate::strip_defaults_from_generics(&mut struct_generics_without_default);

    let mut struct_generics_without_bounds = struct_generics_without_default.clone();
    crate::strip_bounds_from_generics(&mut struct_generics_without_bounds);

    quote!(
        impl #struct_generics_without_default crate::wrapper::RawWrapper for #struct_ident #struct_generics_without_bounds {
            type CType = #raw_field_type;

            fn as_raw_ptr(&self) -> *mut Self::CType {
                std::ptr::addr_of!(self.#raw_field_ident) as *mut _
            }

            fn as_raw(&self) -> &Self::CType {
                &self.#raw_field_ident
            }

            fn from_raw(raw: Self::CType) -> Self {
                Self {
                    #raw_field_ident: raw,
                    #(#other_fields_idents: std::default::Default::default()),*
                }
            }

            unsafe fn mut_from_raw_ptr<'lft>(raw: *mut Self::CType) -> &'lft mut Self {
                (raw as *mut #struct_ident #struct_generics_without_bounds).as_mut().unwrap()
            }
        }

        impl #struct_generics_without_default From<#raw_field_type> for #struct_ident #struct_generics_without_bounds {
            fn from(value: #raw_field_type) -> Self {
                use crate::wrapper::RawWrapper;
                Self::from_raw(value)
            }
        }

        impl #struct_generics_without_default From<#struct_ident #struct_generics_without_bounds> for #raw_field_type {
            fn from(value: #struct_ident #struct_generics_without_bounds) -> Self {
                value.#raw_field_ident
            }
        }
    )
}