• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::ir::comp::{CompInfo, CompKind, Field, FieldMethods};
2 use crate::ir::context::BindgenContext;
3 use crate::ir::item::{IsOpaque, Item};
4 use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
5 
6 /// Generate a manual implementation of `PartialEq` trait for the
7 /// specified compound type.
gen_partialeq_impl( ctx: &BindgenContext, comp_info: &CompInfo, item: &Item, ty_for_impl: &proc_macro2::TokenStream, ) -> Option<proc_macro2::TokenStream>8 pub fn gen_partialeq_impl(
9     ctx: &BindgenContext,
10     comp_info: &CompInfo,
11     item: &Item,
12     ty_for_impl: &proc_macro2::TokenStream,
13 ) -> Option<proc_macro2::TokenStream> {
14     let mut tokens = vec![];
15 
16     if item.is_opaque(ctx, &()) {
17         tokens.push(quote! {
18             &self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
19         });
20     } else if comp_info.kind() == CompKind::Union {
21         assert!(!ctx.options().rust_features().untagged_union);
22         tokens.push(quote! {
23             &self.bindgen_union_field[..] == &other.bindgen_union_field[..]
24         });
25     } else {
26         for base in comp_info.base_members().iter() {
27             if !base.requires_storage(ctx) {
28                 continue;
29             }
30 
31             let ty_item = ctx.resolve_item(base.ty);
32             let field_name = &base.field_name;
33 
34             if ty_item.is_opaque(ctx, &()) {
35                 let field_name = ctx.rust_ident(field_name);
36                 tokens.push(quote! {
37                     &self. #field_name [..] == &other. #field_name [..]
38                 });
39             } else {
40                 tokens.push(gen_field(ctx, ty_item, field_name));
41             }
42         }
43 
44         for field in comp_info.fields() {
45             match *field {
46                 Field::DataMember(ref fd) => {
47                     let ty_item = ctx.resolve_item(fd.ty());
48                     let name = fd.name().unwrap();
49                     tokens.push(gen_field(ctx, ty_item, name));
50                 }
51                 Field::Bitfields(ref bu) => {
52                     for bitfield in bu.bitfields() {
53                         if bitfield.name().is_some() {
54                             let getter_name = bitfield.getter_name();
55                             let name_ident = ctx.rust_ident_raw(getter_name);
56                             tokens.push(quote! {
57                                 self.#name_ident () == other.#name_ident ()
58                             });
59                         }
60                     }
61                 }
62             }
63         }
64     }
65 
66     Some(quote! {
67         fn eq(&self, other: & #ty_for_impl) -> bool {
68             #( #tokens )&&*
69         }
70     })
71 }
72 
gen_field( ctx: &BindgenContext, ty_item: &Item, name: &str, ) -> proc_macro2::TokenStream73 fn gen_field(
74     ctx: &BindgenContext,
75     ty_item: &Item,
76     name: &str,
77 ) -> proc_macro2::TokenStream {
78     fn quote_equals(
79         name_ident: proc_macro2::Ident,
80     ) -> proc_macro2::TokenStream {
81         quote! { self.#name_ident == other.#name_ident }
82     }
83 
84     let name_ident = ctx.rust_ident(name);
85     let ty = ty_item.expect_type();
86 
87     match *ty.kind() {
88         TypeKind::Void |
89         TypeKind::NullPtr |
90         TypeKind::Int(..) |
91         TypeKind::Complex(..) |
92         TypeKind::Float(..) |
93         TypeKind::Enum(..) |
94         TypeKind::TypeParam |
95         TypeKind::UnresolvedTypeRef(..) |
96         TypeKind::Reference(..) |
97         TypeKind::ObjCInterface(..) |
98         TypeKind::ObjCId |
99         TypeKind::ObjCSel |
100         TypeKind::Comp(..) |
101         TypeKind::Pointer(_) |
102         TypeKind::Function(..) |
103         TypeKind::Opaque => quote_equals(name_ident),
104 
105         TypeKind::TemplateInstantiation(ref inst) => {
106             if inst.is_opaque(ctx, ty_item) {
107                 quote! {
108                     &self. #name_ident [..] == &other. #name_ident [..]
109                 }
110             } else {
111                 quote_equals(name_ident)
112             }
113         }
114 
115         TypeKind::Array(_, len) => {
116             if len <= RUST_DERIVE_IN_ARRAY_LIMIT ||
117                 ctx.options().rust_features().larger_arrays
118             {
119                 quote_equals(name_ident)
120             } else {
121                 quote! {
122                     &self. #name_ident [..] == &other. #name_ident [..]
123                 }
124             }
125         }
126         TypeKind::Vector(_, len) => {
127             let self_ids = 0..len;
128             let other_ids = 0..len;
129             quote! {
130                 #(self.#self_ids == other.#other_ids &&)* true
131             }
132         }
133 
134         TypeKind::ResolvedTypeRef(t) |
135         TypeKind::TemplateAlias(t, _) |
136         TypeKind::Alias(t) |
137         TypeKind::BlockPointer(t) => {
138             let inner_item = ctx.resolve_item(t);
139             gen_field(ctx, inner_item, name)
140         }
141     }
142 }
143