use crate::attributes::Instruction;
use crate::verifiers::bytecode::frame::Frame;
use crate::verifiers::bytecode::type_system::VerificationType;
use crate::verifiers::error::{Result, VerifyError};
pub fn handle_i2l(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Integer {
return Err(VerifyError::VerifyError(format!(
"i2l: expected int, got {value}"
)));
}
frame.push_category2(VerificationType::Long)
}
pub fn handle_i2f(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Integer {
return Err(VerifyError::VerifyError(format!(
"i2f: expected int, got {value}"
)));
}
frame.push(VerificationType::Float)
}
pub fn handle_i2d(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Integer {
return Err(VerifyError::VerifyError(format!(
"i2d: expected int, got {value}"
)));
}
frame.push_category2(VerificationType::Double)
}
pub fn handle_l2i(frame: &mut Frame) -> Result<()> {
let value = frame.pop_category2()?;
if value != VerificationType::Long {
return Err(VerifyError::VerifyError(format!(
"l2i: expected long, got {value}"
)));
}
frame.push(VerificationType::Integer)
}
pub fn handle_l2f(frame: &mut Frame) -> Result<()> {
let value = frame.pop_category2()?;
if value != VerificationType::Long {
return Err(VerifyError::VerifyError(format!(
"l2f: expected long, got {value}"
)));
}
frame.push(VerificationType::Float)
}
pub fn handle_l2d(frame: &mut Frame) -> Result<()> {
let value = frame.pop_category2()?;
if value != VerificationType::Long {
return Err(VerifyError::VerifyError(format!(
"l2d: expected long, got {value}"
)));
}
frame.push_category2(VerificationType::Double)
}
pub fn handle_f2i(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Float {
return Err(VerifyError::VerifyError(format!(
"f2i: expected float, got {value}"
)));
}
frame.push(VerificationType::Integer)
}
pub fn handle_f2l(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Float {
return Err(VerifyError::VerifyError(format!(
"f2l: expected float, got {value}"
)));
}
frame.push_category2(VerificationType::Long)
}
pub fn handle_f2d(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Float {
return Err(VerifyError::VerifyError(format!(
"f2d: expected float, got {value}"
)));
}
frame.push_category2(VerificationType::Double)
}
pub fn handle_d2i(frame: &mut Frame) -> Result<()> {
let value = frame.pop_category2()?;
if value != VerificationType::Double {
return Err(VerifyError::VerifyError(format!(
"d2i: expected double, got {value}"
)));
}
frame.push(VerificationType::Integer)
}
pub fn handle_d2l(frame: &mut Frame) -> Result<()> {
let value = frame.pop_category2()?;
if value != VerificationType::Double {
return Err(VerifyError::VerifyError(format!(
"d2l: expected double, got {value}"
)));
}
frame.push_category2(VerificationType::Long)
}
pub fn handle_d2f(frame: &mut Frame) -> Result<()> {
let value = frame.pop_category2()?;
if value != VerificationType::Double {
return Err(VerifyError::VerifyError(format!(
"d2f: expected double, got {value}"
)));
}
frame.push(VerificationType::Float)
}
pub fn handle_i2b(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Integer {
return Err(VerifyError::VerifyError(format!(
"i2b: expected int, got {value}"
)));
}
frame.push(VerificationType::Integer)
}
pub fn handle_i2c(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Integer {
return Err(VerifyError::VerifyError(format!(
"i2c: expected int, got {value}"
)));
}
frame.push(VerificationType::Integer)
}
pub fn handle_i2s(frame: &mut Frame) -> Result<()> {
let value = frame.pop()?;
if value != VerificationType::Integer {
return Err(VerifyError::VerifyError(format!(
"i2s: expected int, got {value}"
)));
}
frame.push(VerificationType::Integer)
}
pub fn dispatch_conversion(instruction: &Instruction, frame: &mut Frame) -> Result<bool> {
match instruction {
Instruction::I2l => handle_i2l(frame)?,
Instruction::I2f => handle_i2f(frame)?,
Instruction::I2d => handle_i2d(frame)?,
Instruction::I2b => handle_i2b(frame)?,
Instruction::I2c => handle_i2c(frame)?,
Instruction::I2s => handle_i2s(frame)?,
Instruction::L2i => handle_l2i(frame)?,
Instruction::L2f => handle_l2f(frame)?,
Instruction::L2d => handle_l2d(frame)?,
Instruction::F2i => handle_f2i(frame)?,
Instruction::F2l => handle_f2l(frame)?,
Instruction::F2d => handle_f2d(frame)?,
Instruction::D2i => handle_d2i(frame)?,
Instruction::D2l => handle_d2l(frame)?,
Instruction::D2f => handle_d2f(frame)?,
_ => return Ok(false),
}
Ok(true)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_i2l_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
handle_i2l(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 2); }
#[test]
fn test_i2l_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let result = handle_i2l(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected int"));
}
#[test]
fn test_i2f_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
handle_i2f(&mut frame).unwrap();
assert_eq!(*frame.peek().unwrap(), VerificationType::Float);
}
#[test]
fn test_i2f_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let result = handle_i2f(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected int"));
}
#[test]
fn test_i2d_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
handle_i2d(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 2); }
#[test]
fn test_i2d_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let result = handle_i2d(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected int"));
}
#[test]
fn test_l2i_success() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
handle_l2i(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 1);
assert_eq!(*frame.peek().unwrap(), VerificationType::Integer);
}
#[test]
fn test_l2i_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
let result = handle_l2i(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected long"));
}
#[test]
fn test_l2f_success() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
handle_l2f(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 1);
assert_eq!(*frame.peek().unwrap(), VerificationType::Float);
}
#[test]
fn test_l2f_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
let result = handle_l2f(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected long"));
}
#[test]
fn test_l2d_success() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
handle_l2d(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 2); }
#[test]
fn test_l2d_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
let result = handle_l2d(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected long"));
}
#[test]
fn test_f2i_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
handle_f2i(&mut frame).unwrap();
assert_eq!(*frame.peek().unwrap(), VerificationType::Integer);
}
#[test]
fn test_f2i_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let result = handle_f2i(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected float"));
}
#[test]
fn test_f2l_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
handle_f2l(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 2); }
#[test]
fn test_f2l_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let result = handle_f2l(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected float"));
}
#[test]
fn test_f2d_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
handle_f2d(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 2);
}
#[test]
fn test_f2d_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let result = handle_f2d(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected float"));
}
#[test]
fn test_d2i_success() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
handle_d2i(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 1);
assert_eq!(*frame.peek().unwrap(), VerificationType::Integer);
}
#[test]
fn test_d2i_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
let result = handle_d2i(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected double"));
}
#[test]
fn test_d2l_success() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
handle_d2l(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 2);
}
#[test]
fn test_d2l_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
let result = handle_d2l(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected double"));
}
#[test]
fn test_d2f_success() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
handle_d2f(&mut frame).unwrap();
assert_eq!(frame.stack_depth(), 1);
assert_eq!(*frame.peek().unwrap(), VerificationType::Float);
}
#[test]
fn test_d2f_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
let result = handle_d2f(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected double"));
}
#[test]
fn test_i2b_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
handle_i2b(&mut frame).unwrap();
assert_eq!(*frame.peek().unwrap(), VerificationType::Integer);
}
#[test]
fn test_i2b_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let result = handle_i2b(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected int"));
}
#[test]
fn test_i2c_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
handle_i2c(&mut frame).unwrap();
assert_eq!(*frame.peek().unwrap(), VerificationType::Integer);
}
#[test]
fn test_i2c_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let result = handle_i2c(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected int"));
}
#[test]
fn test_i2s_success() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
handle_i2s(&mut frame).unwrap();
assert_eq!(*frame.peek().unwrap(), VerificationType::Integer);
}
#[test]
fn test_i2s_wrong_type_fails() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let result = handle_i2s(&mut frame);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("expected int"));
}
#[test]
fn test_dispatch_i2l() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let handled = dispatch_conversion(&Instruction::I2l, &mut frame).unwrap();
assert!(handled);
assert_eq!(frame.stack_depth(), 2);
}
#[test]
fn test_dispatch_i2f() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let handled = dispatch_conversion(&Instruction::I2f, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_i2d() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let handled = dispatch_conversion(&Instruction::I2d, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_i2b() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let handled = dispatch_conversion(&Instruction::I2b, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_i2c() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let handled = dispatch_conversion(&Instruction::I2c, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_i2s() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Integer).unwrap();
let handled = dispatch_conversion(&Instruction::I2s, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_l2i() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
let handled = dispatch_conversion(&Instruction::L2i, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_l2f() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
let handled = dispatch_conversion(&Instruction::L2f, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_l2d() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Long).unwrap();
let handled = dispatch_conversion(&Instruction::L2d, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_f2i() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let handled = dispatch_conversion(&Instruction::F2i, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_f2l() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let handled = dispatch_conversion(&Instruction::F2l, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_f2d() {
let mut frame = Frame::new(5, 10);
frame.push(VerificationType::Float).unwrap();
let handled = dispatch_conversion(&Instruction::F2d, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_d2i() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
let handled = dispatch_conversion(&Instruction::D2i, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_d2l() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
let handled = dispatch_conversion(&Instruction::D2l, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_d2f() {
let mut frame = Frame::new(5, 10);
frame.push_category2(VerificationType::Double).unwrap();
let handled = dispatch_conversion(&Instruction::D2f, &mut frame).unwrap();
assert!(handled);
}
#[test]
fn test_dispatch_non_conversion_instruction() {
let mut frame = Frame::new(5, 10);
let handled = dispatch_conversion(&Instruction::Nop, &mut frame).unwrap();
assert!(!handled);
}
}