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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Types representing constant pool elements

use crate::error::ErrorType;
use std::convert::TryFrom;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum ConstantTag {
    Class = 7,
    Fieldref = 9,
    Methodref = 10,
    InterfaceMethodref = 11,
    String = 8,
    Integer = 3,
    Float = 4,
    Long = 5,
    Double = 6,
    NameAndType = 12,
    Utf8 = 1,
    MethodHandle = 15,
    MethodType = 16,
    InvokeDynamic = 18
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum ReferenceKind {
    GetField = 1,
    GetStatic = 2,
    PutField = 3,
    PutStatic = 4,
    InvokeVirtual = 5,
    InvokeStatic = 6,
    InvokeSpecial = 7,
    NewInvokeSpecial = 8,
    InvokeInterface = 9
}

impl TryFrom<u8> for ConstantTag {
    type Error = ErrorType;

    fn try_from(v: u8) -> Result<ConstantTag, Self::Error> {
        match v {
            x if x == ConstantTag::Class as u8 => Ok(ConstantTag::Class),
            x if x == ConstantTag::Fieldref as u8 => Ok(ConstantTag::Fieldref),
            x if x == ConstantTag::Methodref as u8 => Ok(ConstantTag::Methodref),
            x if x == ConstantTag::InterfaceMethodref as u8 => Ok(ConstantTag::InterfaceMethodref),
            x if x == ConstantTag::String as u8 => Ok(ConstantTag::String),
            x if x == ConstantTag::Integer as u8 => Ok(ConstantTag::Integer),
            x if x == ConstantTag::Float as u8 => Ok(ConstantTag::Float),
            x if x == ConstantTag::Long as u8 => Ok(ConstantTag::Long),
            x if x == ConstantTag::Double as u8 => Ok(ConstantTag::Double),
            x if x == ConstantTag::NameAndType as u8 => Ok(ConstantTag::NameAndType),
            x if x == ConstantTag::Utf8 as u8 => Ok(ConstantTag::Utf8),
            x if x == ConstantTag::MethodHandle as u8 => Ok(ConstantTag::MethodHandle),
            x if x == ConstantTag::MethodType as u8 => Ok(ConstantTag::MethodType),
            x if x == ConstantTag::InvokeDynamic as u8 => Ok(ConstantTag::InvokeDynamic),
            _ => Err(ErrorType::IntegerConversion)
        }
    }
}

impl TryFrom<u8> for ReferenceKind {
    type Error = ErrorType;

    fn try_from(v: u8) -> Result<ReferenceKind, Self::Error> {
        match v {
            x if x == ReferenceKind::GetField as u8 => Ok(ReferenceKind::GetField),
            x if x == ReferenceKind::GetStatic as u8 => Ok(ReferenceKind::GetStatic),
            x if x == ReferenceKind::PutField as u8 => Ok(ReferenceKind::PutField),
            x if x == ReferenceKind::PutStatic as u8 => Ok(ReferenceKind::PutStatic),
            x if x == ReferenceKind::InvokeVirtual as u8 => Ok(ReferenceKind::InvokeVirtual),
            x if x == ReferenceKind::InvokeStatic as u8 => Ok(ReferenceKind::InvokeStatic),
            x if x == ReferenceKind::InvokeSpecial as u8 => Ok(ReferenceKind::InvokeSpecial),
            x if x == ReferenceKind::NewInvokeSpecial as u8 => Ok(ReferenceKind::NewInvokeSpecial),
            x if x == ReferenceKind::InvokeInterface as u8 => Ok(ReferenceKind::InvokeInterface),
            _ => Err(ErrorType::IntegerConversion)
        }
    }
}

/// Represents a constant pool element<br/>
/// See <https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-4.html#jvms-4.4> for more information
#[derive(Debug)]
pub enum Constant<'c> {
    Class {
        tag: ConstantTag,
        name_index: u16
    },
    Fieldref {
        tag: ConstantTag,
        class_index: u16,
        name_and_type_index: u16
    },
    Methodref {
        tag: ConstantTag,
        class_index: u16,
        name_and_type_index: u16
    },
    InterfaceMethodref {
        tag: ConstantTag,
        class_index: u16,
        name_and_type_index: u16
    },
    String {
        tag: ConstantTag,
        string_index: u16
    },
    Integer {
        tag: ConstantTag,
        value: i32
    },
    Float {
        tag: ConstantTag,
        bytes: &'c [u8]
    },
    Long {
        tag: ConstantTag,
        high_bytes: u32,
        low_bytes: u32
    },
    Double {
        tag: ConstantTag,
        high_bytes: u32,
        low_bytes: u32
    },
    NameAndType {
        tag: ConstantTag,
        name_index: u16,
        descriptor_index: u16
    },
    Utf8 {
        tag: ConstantTag,
        length: u16,
        bytes: &'c [u8]
    },
    MethodHandle {
        tag: ConstantTag,
        reference_kind: ReferenceKind,
        reference_index: u16
    },
    MethodType {
        tag: ConstantTag,
        descriptor_index: u16
    },
    InvokeDynamic {
        tag: ConstantTag,
        bootstrap_method_attr_index: u16,
        name_index: u16
    }
}