use super::Stack; use crate::{Byte, Short, Trap}; pub trait Peek { fn peek(stack: &Stack) -> Result where Self: Sized; } impl Peek for () { fn peek(_stack: &Stack) -> Result { Ok(()) } } impl Peek for Byte { fn peek(stack: &Stack) -> Result { if stack.ptr < 1 { return Err(Trap::StackUnderflow); } let a = { let val = stack.data[stack.ptr as usize - 1]; Byte::from(val) }; Ok(a) } } impl Peek for bool { fn peek(stack: &Stack) -> Result { let a = ::peek(stack)?; Ok(bool::from(a)) } } impl Peek for (Byte, Byte) { fn peek(stack: &Stack) -> Result { if stack.ptr < 2 { return Err(Trap::StackUnderflow); } let b = { let val = stack.data[stack.ptr as usize - 1]; Byte::from(val) }; let a = { let val = stack.data[stack.ptr as usize - 2]; Byte::from(val) }; Ok((a, b)) } } impl Peek for (bool, Byte) { fn peek(stack: &Stack) -> Result { let (a, b) = <(Byte, Byte)>::peek(stack)?; Ok((bool::from(a), b)) } } impl Peek for (Byte, Byte, Byte) { fn peek(stack: &Stack) -> Result { if stack.ptr < 2 { return Err(Trap::StackUnderflow); } let c = { let val = stack.data[stack.ptr as usize - 1]; Byte::from(val) }; let b = { let val = stack.data[stack.ptr as usize - 2]; Byte::from(val) }; let a = { let val = stack.data[stack.ptr as usize - 3]; Byte::from(val) }; Ok((a, b, c)) } } impl Peek for Short { fn peek(stack: &Stack) -> Result { if stack.ptr <= 2 - 1 { return Err(Trap::StackUnderflow); } let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); Short::from(val) }; Ok(a) } } impl Peek for (Byte, Short) { fn peek(stack: &Stack) -> Result { if stack.ptr <= 2 - 1 { return Err(Trap::StackUnderflow); } let b = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); Short::from(val) }; let a = { let val = stack.data[stack.ptr as usize - 3]; Byte::from(val) }; Ok((a, b)) } } impl Peek for (bool, Short) { fn peek(stack: &Stack) -> Result { let (a, b) = <(Byte, Short)>::peek(stack)?; Ok((bool::from(a), b)) } } impl Peek for (Short, Byte) { fn peek(stack: &Stack) -> Result { if stack.ptr <= 2 - 1 { return Err(Trap::StackUnderflow); } let b = { let val = stack.data[stack.ptr as usize - 1]; Byte::from(val) }; let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 3], stack.data[stack.ptr as usize - 2], ]); Short::from(val) }; Ok((a, b)) } } impl Peek for (Short, Short) { fn peek(stack: &Stack) -> Result { if stack.ptr <= 2 - 1 { return Err(Trap::StackUnderflow); } let b = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); Short::from(val) }; let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 4], stack.data[stack.ptr as usize - 3], ]); Short::from(val) }; Ok((a, b)) } } impl Peek for (Short, Short, Short) { fn peek(stack: &Stack) -> Result { if stack.ptr <= 2 - 1 { return Err(Trap::StackUnderflow); } let c = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); Short::from(val) }; let b = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 4], stack.data[stack.ptr as usize - 3], ]); Short::from(val) }; let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 6], stack.data[stack.ptr as usize - 5], ]); Short::from(val) }; Ok((a, b, c)) } }