File: impl_partialeq.rs

package info (click to toggle)
firefox 147.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 4,683,324 kB
  • sloc: cpp: 7,607,156; javascript: 6,532,492; ansic: 3,775,158; python: 1,415,368; xml: 634,556; asm: 438,949; java: 186,241; sh: 62,751; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (114 lines) | stat: -rw-r--r-- 3,606 bytes parent folder | download | duplicates (4)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use crate::ir::comp::{CompInfo, CompKind, Field, FieldMethods};
use crate::ir::context::BindgenContext;
use crate::ir::item::{IsOpaque, Item};
use crate::ir::ty::TypeKind;

/// 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() {
            if !base.requires_storage(ctx) {
                continue;
            }

            let ty_item = ctx.resolve_item(base.ty);
            let field_name = &base.field_name;
            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::Array(..) |
        TypeKind::TemplateInstantiation(..) |
        TypeKind::Opaque => quote_equals(&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)
        }
    }
}