forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			142 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::ir::comp::{CompInfo, CompKind, Field, FieldMethods};
 | |
| use crate::ir::context::BindgenContext;
 | |
| use crate::ir::item::{IsOpaque, Item};
 | |
| use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
 | |
| 
 | |
| /// Generate a manual implementation of `PartialEq` trait for the
 | |
| /// specified compound type.
 | |
| pub(crate) fn gen_partialeq_impl(
 | |
|     ctx: &BindgenContext,
 | |
|     comp_info: &CompInfo,
 | |
|     item: &Item,
 | |
|     ty_for_impl: &proc_macro2::TokenStream,
 | |
| ) -> Option<proc_macro2::TokenStream> {
 | |
|     let mut tokens = vec![];
 | |
| 
 | |
|     if item.is_opaque(ctx, &()) {
 | |
|         tokens.push(quote! {
 | |
|             &self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
 | |
|         });
 | |
|     } else if comp_info.kind() == CompKind::Union {
 | |
|         assert!(!ctx.options().untagged_union);
 | |
|         tokens.push(quote! {
 | |
|             &self.bindgen_union_field[..] == &other.bindgen_union_field[..]
 | |
|         });
 | |
|     } else {
 | |
|         for base in comp_info.base_members().iter() {
 | |
|             if !base.requires_storage(ctx) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             let ty_item = ctx.resolve_item(base.ty);
 | |
|             let field_name = &base.field_name;
 | |
| 
 | |
|             if ty_item.is_opaque(ctx, &()) {
 | |
|                 let field_name = ctx.rust_ident(field_name);
 | |
|                 tokens.push(quote! {
 | |
|                     &self. #field_name [..] == &other. #field_name [..]
 | |
|                 });
 | |
|             } else {
 | |
|                 tokens.push(gen_field(ctx, ty_item, field_name));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         for field in comp_info.fields() {
 | |
|             match *field {
 | |
|                 Field::DataMember(ref fd) => {
 | |
|                     let ty_item = ctx.resolve_item(fd.ty());
 | |
|                     let name = fd.name().unwrap();
 | |
|                     tokens.push(gen_field(ctx, ty_item, name));
 | |
|                 }
 | |
|                 Field::Bitfields(ref bu) => {
 | |
|                     for bitfield in bu.bitfields() {
 | |
|                         if bitfield.name().is_some() {
 | |
|                             let getter_name = bitfield.getter_name();
 | |
|                             let name_ident = ctx.rust_ident_raw(getter_name);
 | |
|                             tokens.push(quote! {
 | |
|                                 self.#name_ident () == other.#name_ident ()
 | |
|                             });
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     Some(quote! {
 | |
|         fn eq(&self, other: & #ty_for_impl) -> bool {
 | |
|             #( #tokens )&&*
 | |
|         }
 | |
|     })
 | |
| }
 | |
| 
 | |
| fn gen_field(
 | |
|     ctx: &BindgenContext,
 | |
|     ty_item: &Item,
 | |
|     name: &str,
 | |
| ) -> proc_macro2::TokenStream {
 | |
|     fn quote_equals(
 | |
|         name_ident: proc_macro2::Ident,
 | |
|     ) -> proc_macro2::TokenStream {
 | |
|         quote! { self.#name_ident == other.#name_ident }
 | |
|     }
 | |
| 
 | |
|     let name_ident = ctx.rust_ident(name);
 | |
|     let ty = ty_item.expect_type();
 | |
| 
 | |
|     match *ty.kind() {
 | |
|         TypeKind::Void |
 | |
|         TypeKind::NullPtr |
 | |
|         TypeKind::Int(..) |
 | |
|         TypeKind::Complex(..) |
 | |
|         TypeKind::Float(..) |
 | |
|         TypeKind::Enum(..) |
 | |
|         TypeKind::TypeParam |
 | |
|         TypeKind::UnresolvedTypeRef(..) |
 | |
|         TypeKind::Reference(..) |
 | |
|         TypeKind::ObjCInterface(..) |
 | |
|         TypeKind::ObjCId |
 | |
|         TypeKind::ObjCSel |
 | |
|         TypeKind::Comp(..) |
 | |
|         TypeKind::Pointer(_) |
 | |
|         TypeKind::Function(..) |
 | |
|         TypeKind::Opaque => quote_equals(name_ident),
 | |
| 
 | |
|         TypeKind::TemplateInstantiation(ref inst) => {
 | |
|             if inst.is_opaque(ctx, ty_item) {
 | |
|                 quote! {
 | |
|                     &self. #name_ident [..] == &other. #name_ident [..]
 | |
|                 }
 | |
|             } else {
 | |
|                 quote_equals(name_ident)
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         TypeKind::Array(_, len) => {
 | |
|             if len <= RUST_DERIVE_IN_ARRAY_LIMIT ||
 | |
|                 ctx.options().rust_features().larger_arrays
 | |
|             {
 | |
|                 quote_equals(name_ident)
 | |
|             } else {
 | |
|                 quote! {
 | |
|                     &self. #name_ident [..] == &other. #name_ident [..]
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         TypeKind::Vector(_, len) => {
 | |
|             let self_ids = 0..len;
 | |
|             let other_ids = 0..len;
 | |
|             quote! {
 | |
|                 #(self.#self_ids == other.#other_ids &&)* true
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         TypeKind::ResolvedTypeRef(t) |
 | |
|         TypeKind::TemplateAlias(t, _) |
 | |
|         TypeKind::Alias(t) |
 | |
|         TypeKind::BlockPointer(t) => {
 | |
|             let inner_item = ctx.resolve_item(t);
 | |
|             gen_field(ctx, inner_item, name)
 | |
|         }
 | |
|     }
 | |
| }
 | 
