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