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
115
116
117
118
119
120
121
122
use super::*;

pub trait Decode {
    fn decode(file: usize, code: usize) -> Self;
}

pub enum AttributeType {
    MemberRef(MemberRef),
}

impl Decode for AttributeType {
    fn decode(file: usize, code: usize) -> Self {
        let (kind, row) = (code & ((1 << 3) - 1), (code >> 3) - 1);
        match kind {
            3 => Self::MemberRef(MemberRef(Row::new(row, TABLE_MEMBERREF, file))),
            _ => unimplemented!(),
        }
    }
}

pub enum HasAttribute {
    MethodDef(MethodDef),
    Field(Field),
    TypeRef(TypeRef),
    TypeDef(TypeDef),
    Param(Param),
    InterfaceImpl(InterfaceImpl),
    MemberRef(MemberRef),
    TypeSpec(TypeSpec),
    GenericParam(GenericParam),
}

impl HasAttribute {
    pub fn encode(&self) -> usize {
        (match self {
            Self::MethodDef(row) => (row.0.row + 1) << 5,
            Self::Field(row) => ((row.0.row + 1) << 5) | 1,
            Self::TypeRef(row) => ((row.0.row + 1) << 5) | 2,
            Self::TypeDef(row) => ((row.0.row + 1) << 5) | 3,
            Self::Param(row) => ((row.0.row + 1) << 5) | 4,
            Self::InterfaceImpl(row) => ((row.0.row + 1) << 5) | 5,
            Self::MemberRef(row) => ((row.0.row + 1) << 5) | 6,
            Self::TypeSpec(row) => ((row.0.row + 1) << 5) | 13,
            Self::GenericParam(row) => ((row.0.row + 1) << 5) | 19,
        }) as _
    }
}

#[derive(Clone)]
pub enum HasConstant {
    Field(Field),
}

impl HasConstant {
    pub fn encode(&self) -> usize {
        (match self {
            Self::Field(row) => (row.0.row + 1) << 2,
        }) as _
    }
}

#[derive(Clone)]
pub enum MemberForwarded {
    MethodDef(MethodDef),
}

impl MemberForwarded {
    pub fn encode(&self) -> usize {
        (match self {
            Self::MethodDef(value) => ((value.0.row + 1) << 1) | 1,
        }) as _
    }
}

pub enum MemberRefParent {
    TypeRef(TypeRef),
}

impl Decode for MemberRefParent {
    fn decode(file: usize, code: usize) -> Self {
        let (kind, row) = (code & ((1 << 3) - 1), (code >> 3) - 1);
        match kind {
            1 => Self::TypeRef(TypeRef(Row::new(row, TABLE_TYPEREF, file))),
            _ => unimplemented!(),
        }
    }
}

#[derive(Copy, Clone)]
pub enum TypeDefOrRef {
    None,
    TypeDef(TypeDef),
    TypeRef(TypeRef),
    TypeSpec(TypeSpec),
}

impl Decode for TypeDefOrRef {
    fn decode(file: usize, code: usize) -> Self {
        if code == 0 {
            return Self::None;
        }
        let (kind, row) = (code & ((1 << 2) - 1), (code >> 2) - 1);
        match kind {
            0 => Self::TypeDef(TypeDef(Row::new(row, TABLE_TYPEDEF, file))),
            1 => Self::TypeRef(TypeRef(Row::new(row, TABLE_TYPEREF, file))),
            2 => Self::TypeSpec(TypeSpec(Row::new(row, TABLE_TYPESPEC, file))),
            _ => unimplemented!(),
        }
    }
}

pub enum TypeOrMethodDef {
    TypeDef(TypeDef),
}

impl TypeOrMethodDef {
    pub fn encode(&self) -> usize {
        (match self {
            Self::TypeDef(value) => (value.0.row + 1) << 1,
        }) as _
    }
}